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';
|
||||
|
|
@ -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 {ViewDefinition, DirectiveMetadata} from 'angular2/src/render/api';
|
||||
import {Lexer, Parser} from 'angular2/change_detection';
|
||||
import {ElementBinderBuilder} from 'angular2/src/render/dom/view/proto_view_builder';
|
||||
|
||||
export function main() {
|
||||
describe('DirectiveParser', () => {
|
||||
var parser, annotatedDirectives;
|
||||
|
||||
beforeEach( () => {
|
||||
beforeEach(() => {
|
||||
annotatedDirectives = [
|
||||
someComponent,
|
||||
someComponent2,
|
||||
|
@ -35,20 +36,21 @@ export function main() {
|
|||
if (isBlank(directives)) directives = annotatedDirectives;
|
||||
|
||||
return new CompilePipeline([
|
||||
new MockStep( (parent, current, control) => {
|
||||
if (isPresent(propertyBindings)) {
|
||||
StringMapWrapper.forEach(propertyBindings, (ast, name) => {
|
||||
current.bindElement().bindProperty(name, ast);
|
||||
});
|
||||
}
|
||||
}),
|
||||
new MockStep((parent, current, control) =>
|
||||
{
|
||||
if (isPresent(propertyBindings)) {
|
||||
StringMapWrapper.forEach(propertyBindings, (ast, name) => {
|
||||
current.bindElement().bindProperty(name, ast);
|
||||
});
|
||||
}
|
||||
}),
|
||||
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);
|
||||
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', () => {
|
||||
|
@ -58,16 +60,14 @@ export function main() {
|
|||
|
||||
it('should detect directives in attributes', () => {
|
||||
var results = process(el('<div some-decor></div>'));
|
||||
expect(results[0].directives[0].directiveIndex).toBe(
|
||||
annotatedDirectives.indexOf(someDirective)
|
||||
);
|
||||
expect(results[0].directives[0].directiveIndex)
|
||||
.toBe(annotatedDirectives.indexOf(someDirective));
|
||||
});
|
||||
|
||||
it('should detect directives with multiple attributes', () => {
|
||||
var results = process(el('<input type=text control=one></input>'));
|
||||
expect(results[0].directives[0].directiveIndex).toBe(
|
||||
annotatedDirectives.indexOf(decoratorWithMultipleAttrs)
|
||||
);
|
||||
expect(results[0].directives[0].directiveIndex)
|
||||
.toBe(annotatedDirectives.indexOf(decoratorWithMultipleAttrs));
|
||||
});
|
||||
|
||||
it('should compile children by default', () => {
|
||||
|
@ -81,36 +81,26 @@ export function main() {
|
|||
});
|
||||
|
||||
it('should bind directive properties from bound properties', () => {
|
||||
var results = process(
|
||||
el('<div some-decor-props></div>'),
|
||||
{
|
||||
'elProp': parser.parseBinding('someExpr', '')
|
||||
}
|
||||
);
|
||||
var results = process(el('<div some-decor-props></div>'),
|
||||
{'elProp': parser.parseBinding('someExpr', '')});
|
||||
var directiveBinding = results[0].directives[0];
|
||||
expect(MapWrapper.get(directiveBinding.propertyBindings, 'dirProp').source)
|
||||
.toEqual('someExpr');
|
||||
.toEqual('someExpr');
|
||||
});
|
||||
|
||||
it('should bind directive properties with pipes', () => {
|
||||
var results = process(
|
||||
el('<div some-decor-props></div>'),
|
||||
{
|
||||
'elProp': parser.parseBinding('someExpr', '')
|
||||
}
|
||||
);
|
||||
var results = process(el('<div some-decor-props></div>'),
|
||||
{'elProp': parser.parseBinding('someExpr', '')});
|
||||
var directiveBinding = results[0].directives[0];
|
||||
var pipedProp = MapWrapper.get(directiveBinding.propertyBindings, 'doubleProp');
|
||||
var simpleProp = MapWrapper.get(directiveBinding.propertyBindings, 'dirProp');
|
||||
var pipedProp = <any>MapWrapper.get(directiveBinding.propertyBindings, 'doubleProp');
|
||||
var simpleProp = <any>MapWrapper.get(directiveBinding.propertyBindings, 'dirProp');
|
||||
expect(pipedProp.ast.name).toEqual('double');
|
||||
expect(pipedProp.ast.exp).toEqual(simpleProp.ast);
|
||||
expect(simpleProp.source).toEqual('someExpr');
|
||||
});
|
||||
|
||||
it('should bind directive properties from attribute values', () => {
|
||||
var results = process(
|
||||
el('<div some-decor-props el-prop="someValue"></div>')
|
||||
);
|
||||
var results = process(el('<div some-decor-props el-prop="someValue"></div>'));
|
||||
var directiveBinding = results[0].directives[0];
|
||||
var simpleProp = MapWrapper.get(directiveBinding.propertyBindings, 'dirProp');
|
||||
expect(simpleProp.source).toEqual('someValue');
|
||||
|
@ -160,9 +150,7 @@ export function main() {
|
|||
});
|
||||
|
||||
it('should bind directive events', () => {
|
||||
var results = process(
|
||||
el('<div some-decor-events></div>')
|
||||
);
|
||||
var results = process(el('<div some-decor-events></div>'));
|
||||
var directiveBinding = results[0].directives[0];
|
||||
expect(directiveBinding.eventBindings.length).toEqual(1);
|
||||
var eventBinding = directiveBinding.eventBindings[0];
|
||||
|
@ -171,9 +159,7 @@ export function main() {
|
|||
});
|
||||
|
||||
it('should bind directive global events', () => {
|
||||
var results = process(
|
||||
el('<div some-decor-globalevents></div>')
|
||||
);
|
||||
var results = process(el('<div some-decor-globalevents></div>'));
|
||||
var directiveBinding = results[0].directives[0];
|
||||
expect(directiveBinding.eventBindings.length).toEqual(1);
|
||||
var eventBinding = directiveBinding.eventBindings[0];
|
||||
|
@ -182,83 +168,61 @@ export function main() {
|
|||
});
|
||||
|
||||
it('should bind directive host actions', () => {
|
||||
var results = process(
|
||||
el('<div some-decor-host-actions></div>')
|
||||
);
|
||||
var results = process(el('<div some-decor-host-actions></div>'));
|
||||
var directiveBinding = results[0].directives[0];
|
||||
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', () => {
|
||||
it('should save the component id', () => {
|
||||
var results = process(
|
||||
el('<some-comp></some-comp>')
|
||||
);
|
||||
var results = process(el('<some-comp></some-comp>'));
|
||||
expect(results[0].componentId).toEqual('someComponent');
|
||||
});
|
||||
|
||||
it('should throw when the provided selector is not an element selector', () => {
|
||||
expect( () => {
|
||||
createPipeline(null, [componentWithNonElementSelector]);
|
||||
}).toThrowError(`Component 'componentWithNonElementSelector' can only have an element selector, but had '[attr]'`);
|
||||
expect(() => { createPipeline(null, [componentWithNonElementSelector]); })
|
||||
.toThrowError(
|
||||
`Component 'componentWithNonElementSelector' can only have an element selector, but had '[attr]'`);
|
||||
});
|
||||
|
||||
it('should not allow multiple component directives on the same element', () => {
|
||||
expect( () => {
|
||||
process(
|
||||
el('<some-comp></some-comp>'),
|
||||
null,
|
||||
[someComponent, someComponentDup]
|
||||
);
|
||||
}).toThrowError(new RegExp('Only one component directive is allowed per element' ));
|
||||
expect(() => {
|
||||
process(el('<some-comp></some-comp>'), 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', () => {
|
||||
var results = process(
|
||||
el('<some-comp some-decor></some-comp>')
|
||||
);
|
||||
expect(annotatedDirectives[results[0].directives[0].directiveIndex].id).toEqual('someComponent');
|
||||
expect(annotatedDirectives[results[0].directives[1].directiveIndex].id).toEqual('someDirective');
|
||||
var results = process(el('<some-comp some-decor></some-comp>'));
|
||||
expect(annotatedDirectives[results[0].directives[0].directiveIndex].id)
|
||||
.toEqual('someComponent');
|
||||
expect(annotatedDirectives[results[0].directives[1].directiveIndex].id)
|
||||
.toEqual('someDirective');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@IMPLEMENTS(CompileStep)
|
||||
class MockStep {
|
||||
processClosure:Function;
|
||||
constructor(process) {
|
||||
this.processClosure = process;
|
||||
}
|
||||
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
||||
class MockStep implements CompileStep {
|
||||
processClosure: Function;
|
||||
constructor(process) { this.processClosure = process; }
|
||||
process(parent: CompileElement, current: CompileElement, control: CompileControl) {
|
||||
this.processClosure(parent, current, control);
|
||||
}
|
||||
}
|
||||
|
||||
var someComponent = new DirectiveMetadata({
|
||||
selector: 'some-comp',
|
||||
id: 'someComponent',
|
||||
type: DirectiveMetadata.COMPONENT_TYPE
|
||||
});
|
||||
var someComponent = new DirectiveMetadata(
|
||||
{selector: 'some-comp', id: 'someComponent', type: DirectiveMetadata.COMPONENT_TYPE});
|
||||
|
||||
var someComponentDup = new DirectiveMetadata({
|
||||
selector: 'some-comp',
|
||||
id: 'someComponentDup',
|
||||
type: DirectiveMetadata.COMPONENT_TYPE
|
||||
});
|
||||
var someComponentDup = new DirectiveMetadata(
|
||||
{selector: 'some-comp', id: 'someComponentDup', type: DirectiveMetadata.COMPONENT_TYPE});
|
||||
|
||||
var someComponent2 = new DirectiveMetadata({
|
||||
selector: 'some-comp2',
|
||||
id: 'someComponent2',
|
||||
type: DirectiveMetadata.COMPONENT_TYPE
|
||||
});
|
||||
var someComponent2 = new DirectiveMetadata(
|
||||
{selector: 'some-comp2', id: 'someComponent2', type: DirectiveMetadata.COMPONENT_TYPE});
|
||||
|
||||
var someDirective = new DirectiveMetadata({
|
||||
selector: '[some-decor]',
|
||||
id: 'someDirective',
|
||||
type: DirectiveMetadata.DIRECTIVE_TYPE
|
||||
});
|
||||
var someDirective = new DirectiveMetadata(
|
||||
{selector: '[some-decor]', id: 'someDirective', type: DirectiveMetadata.DIRECTIVE_TYPE});
|
||||
|
||||
var someDirectiveIgnoringChildren = new DirectiveMetadata({
|
||||
selector: '[some-decor-ignoring-children]',
|
||||
|
@ -275,47 +239,34 @@ var decoratorWithMultipleAttrs = new DirectiveMetadata({
|
|||
|
||||
var someDirectiveWithProps = new DirectiveMetadata({
|
||||
selector: '[some-decor-props]',
|
||||
properties: MapWrapper.createFromStringMap({
|
||||
'dirProp': 'elProp',
|
||||
'doubleProp': 'elProp | double'
|
||||
}),
|
||||
properties:
|
||||
MapWrapper.createFromStringMap({'dirProp': 'elProp', 'doubleProp': 'elProp | double'}),
|
||||
readAttributes: ['some-attr']
|
||||
});
|
||||
|
||||
var someDirectiveWithHostProperties = new DirectiveMetadata({
|
||||
selector: '[some-decor-with-host-props]',
|
||||
hostProperties: MapWrapper.createFromStringMap({
|
||||
'dirProp': 'hostProperty'
|
||||
})
|
||||
hostProperties: MapWrapper.createFromStringMap({'dirProp': 'hostProperty'})
|
||||
});
|
||||
|
||||
var someDirectiveWithHostAttributes = new DirectiveMetadata({
|
||||
selector: '[some-decor-with-host-attrs]',
|
||||
hostAttributes: MapWrapper.createFromStringMap({
|
||||
'attr_name': 'attr_val',
|
||||
'class': 'foo bar'
|
||||
})
|
||||
hostAttributes: MapWrapper.createFromStringMap({'attr_name': 'attr_val', 'class': 'foo bar'})
|
||||
});
|
||||
|
||||
var someDirectiveWithEvents = new DirectiveMetadata({
|
||||
selector: '[some-decor-events]',
|
||||
hostListeners: MapWrapper.createFromStringMap({
|
||||
'click': 'doIt()'
|
||||
})
|
||||
hostListeners: MapWrapper.createFromStringMap({'click': 'doIt()'})
|
||||
});
|
||||
|
||||
var someDirectiveWithHostActions = new DirectiveMetadata({
|
||||
selector: '[some-decor-host-actions]',
|
||||
hostActions: MapWrapper.createFromStringMap({
|
||||
'focus': 'focus()'
|
||||
})
|
||||
hostActions: MapWrapper.createFromStringMap({'focus': 'focus()'})
|
||||
});
|
||||
|
||||
var someDirectiveWithGlobalEvents = new DirectiveMetadata({
|
||||
selector: '[some-decor-globalevents]',
|
||||
hostListeners: MapWrapper.createFromStringMap({
|
||||
'window:resize': 'doItGlobal()'
|
||||
})
|
||||
hostListeners: MapWrapper.createFromStringMap({'window:resize': 'doItGlobal()'})
|
||||
});
|
||||
|
||||
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 {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 {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', () => {
|
||||
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 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 pipeline = new CompilePipeline([new MockStep((parent, current, control) => {
|
||||
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);
|
||||
|
@ -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 step0Log = [];
|
||||
var step1Log = [];
|
||||
var pipeline = new CompilePipeline([
|
||||
createWrapperStep('wrap0', step0Log),
|
||||
createLoggerStep(step1Log)
|
||||
]);
|
||||
var pipeline = new CompilePipeline(
|
||||
[createWrapperStep('wrap0', step0Log), createLoggerStep(step1Log)]);
|
||||
var result = pipeline.process(element);
|
||||
expect(step0Log).toEqual(['1', '1<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', () => {
|
||||
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 step1Log = [];
|
||||
var step2Log = [];
|
||||
|
@ -127,7 +128,8 @@ export function main() {
|
|||
});
|
||||
|
||||
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 step1Log = [];
|
||||
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 step0Log = [];
|
||||
var step1Log = [];
|
||||
var pipeline = new CompilePipeline([
|
||||
createWrapperStep('wrap0', step0Log),
|
||||
createLoggerStep(step1Log)
|
||||
]);
|
||||
var pipeline = new CompilePipeline(
|
||||
[createWrapperStep('wrap0', step0Log), createLoggerStep(step1Log)]);
|
||||
var result = pipeline.process(element);
|
||||
expect(step0Log).toEqual(['1', '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 newChild = new CompileElement(el('<div id="3"></div>'));
|
||||
var pipeline = new CompilePipeline([
|
||||
new MockStep((parent, current, control) => {
|
||||
if (StringWrapper.equals(DOM.getAttribute(current.element, 'id'), '1')) {
|
||||
control.addChild(newChild);
|
||||
}
|
||||
}),
|
||||
new MockStep((parent, current, control) =>
|
||||
{
|
||||
if (StringWrapper.equals(DOM.getAttribute(current.element, 'id'), '1')) {
|
||||
control.addChild(newChild);
|
||||
}
|
||||
}),
|
||||
createLoggerStep(resultLog)
|
||||
]);
|
||||
var result = pipeline.process(element);
|
||||
|
@ -182,20 +183,16 @@ export function main() {
|
|||
});
|
||||
}
|
||||
|
||||
@IMPLEMENTS(CompileStep)
|
||||
class MockStep {
|
||||
processClosure:Function;
|
||||
constructor(process) {
|
||||
this.processClosure = process;
|
||||
}
|
||||
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
||||
class MockStep implements CompileStep {
|
||||
processClosure: Function;
|
||||
constructor(process) { this.processClosure = process; }
|
||||
process(parent: CompileElement, current: CompileElement, control: CompileControl) {
|
||||
this.processClosure(parent, current, control);
|
||||
}
|
||||
}
|
||||
|
||||
@IMPLEMENTS(CompileStep)
|
||||
export class IgnoreChildrenStep {
|
||||
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
||||
export class IgnoreChildrenStep implements CompileStep {
|
||||
process(parent: CompileElement, current: CompileElement, control: CompileControl) {
|
||||
var attributeMap = DOM.attributeMap(current.element);
|
||||
if (MapWrapper.contains(attributeMap, 'ignore-children')) {
|
||||
current.compileChildren = false;
|
||||
|
@ -203,9 +200,8 @@ export class IgnoreChildrenStep {
|
|||
}
|
||||
}
|
||||
|
||||
@IMPLEMENTS(CompileStep)
|
||||
class IgnoreCurrentElementStep {
|
||||
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
||||
class IgnoreCurrentElementStep implements CompileStep {
|
||||
process(parent: CompileElement, current: CompileElement, control: CompileControl) {
|
||||
var attributeMap = DOM.attributeMap(current.element);
|
||||
if (MapWrapper.contains(attributeMap, 'ignore-current')) {
|
||||
control.ignoreCurrentElement();
|
||||
|
@ -222,9 +218,7 @@ function logEntry(log, parent, current) {
|
|||
}
|
||||
|
||||
function createLoggerStep(log) {
|
||||
return new MockStep((parent, current, control) => {
|
||||
logEntry(log, parent, current);
|
||||
});
|
||||
return new MockStep((parent, current, control) => { logEntry(log, parent, current); });
|
||||
}
|
||||
|
||||
function createWrapperStep(wrapperId, log) {
|
||||
|
@ -244,8 +238,6 @@ function createWrapperStep(wrapperId, log) {
|
|||
|
||||
function resultIdLog(result) {
|
||||
var idLog = [];
|
||||
ListWrapper.forEach(result, (current) => {
|
||||
logEntry(idLog, null, current);
|
||||
});
|
||||
ListWrapper.forEach(result, (current) => { logEntry(idLog, null, current); });
|
||||
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 {CompileControl} from 'angular2/src/render/dom/compiler/compile_control';
|
||||
import {Lexer, Parser} from 'angular2/change_detection';
|
||||
import {ElementBinderBuilder} from 'angular2/src/render/dom/view/proto_view_builder';
|
||||
|
||||
var EMPTY_MAP = MapWrapper.create();
|
||||
|
||||
|
@ -14,19 +15,19 @@ export function main() {
|
|||
describe('PropertyBindingParser', () => {
|
||||
function createPipeline(hasNestedProtoView = false) {
|
||||
return new CompilePipeline([
|
||||
new MockStep((parent, current, control) => {
|
||||
if (hasNestedProtoView) {
|
||||
current.bindElement().bindNestedProtoView(el('<template></template>'));
|
||||
}
|
||||
}),
|
||||
new PropertyBindingParser(new Parser(new Lexer()))]);
|
||||
new MockStep((parent, current, control) =>
|
||||
{
|
||||
if (hasNestedProtoView) {
|
||||
current.bindElement().bindNestedProtoView(el('<template></template>'));
|
||||
}
|
||||
}),
|
||||
new PropertyBindingParser(new Parser(new Lexer()))
|
||||
]);
|
||||
}
|
||||
|
||||
function process(element, hasNestedProtoView = false) {
|
||||
return ListWrapper.map(
|
||||
createPipeline(hasNestedProtoView).process(element),
|
||||
(compileElement) => compileElement.inheritedElementBinder
|
||||
);
|
||||
function process(element, hasNestedProtoView = false): List<ElementBinderBuilder> {
|
||||
return ListWrapper.map(createPipeline(hasNestedProtoView).process(element),
|
||||
(compileElement) => compileElement.inheritedElementBinder);
|
||||
}
|
||||
|
||||
it('should detect [] syntax', () => {
|
||||
|
@ -44,9 +45,8 @@ export function main() {
|
|||
expect(MapWrapper.get(results[0].propertyBindings, 'a').source).toEqual('b');
|
||||
});
|
||||
|
||||
it('should detect bind- syntax only if an attribute name starts with bind', () => {
|
||||
expect(process(el('<div _bind-a="b"></div>'))[0]).toEqual(null);
|
||||
});
|
||||
it('should detect bind- syntax only if an attribute name starts with bind',
|
||||
() => { expect(process(el('<div _bind-a="b"></div>'))[0]).toEqual(null); });
|
||||
|
||||
it('should detect interpolation syntax', () => {
|
||||
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', () => {
|
||||
var results = process(el('<template var-george="washington"></p>'), true);
|
||||
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', () => {
|
||||
var results = process(el('<template #george="washington"></template>'), true);
|
||||
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 using shorthand syntax on the nestedProtoView',
|
||||
() => {
|
||||
var results = process(el('<template #george="washington"></template>'), true);
|
||||
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', () => {
|
||||
var results = process(el('<p var-george="washington"></p>'));
|
||||
|
@ -165,13 +168,10 @@ export function main() {
|
|||
});
|
||||
}
|
||||
|
||||
@IMPLEMENTS(CompileStep)
|
||||
class MockStep {
|
||||
processClosure:Function;
|
||||
constructor(process) {
|
||||
this.processClosure = process;
|
||||
}
|
||||
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
||||
class MockStep implements CompileStep {
|
||||
processClosure: Function;
|
||||
constructor(process) { this.processClosure = process; }
|
||||
process(parent: CompileElement, current: CompileElement, control: CompileControl) {
|
||||
this.processClosure(parent, current, control);
|
||||
}
|
||||
}
|
|
@ -8,9 +8,7 @@ export function main() {
|
|||
describe('SelectorMatcher', () => {
|
||||
var matcher, matched, selectableCollector, s1, s2, s3, s4;
|
||||
|
||||
function reset() {
|
||||
matched = ListWrapper.create();
|
||||
}
|
||||
function reset() { matched = ListWrapper.create(); }
|
||||
|
||||
beforeEach(() => {
|
||||
reset();
|
||||
|
@ -18,52 +16,58 @@ export function main() {
|
|||
selectableCollector = (selector, context) => {
|
||||
ListWrapper.push(matched, selector);
|
||||
ListWrapper.push(matched, context);
|
||||
}
|
||||
};
|
||||
matcher = new SelectorMatcher();
|
||||
});
|
||||
|
||||
it('should select by element name case insensitive', () => {
|
||||
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(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', () => {
|
||||
matcher.addSelectables(s1 = CssSelector.parse('.someClass'), 1);
|
||||
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(matcher.match(CssSelector.parse('.SOMECLASS')[0], selectableCollector)).toEqual(true);
|
||||
expect(matched).toEqual([s1[0],1]);
|
||||
expect(matched).toEqual([s1[0], 1]);
|
||||
|
||||
reset();
|
||||
expect(matcher.match(CssSelector.parse('.someClass.class2')[0], selectableCollector)).toEqual(true);
|
||||
expect(matched).toEqual([s1[0],1,s2[0],2]);
|
||||
expect(matcher.match(CssSelector.parse('.someClass.class2')[0], selectableCollector))
|
||||
.toEqual(true);
|
||||
expect(matched).toEqual([s1[0], 1, s2[0], 2]);
|
||||
});
|
||||
|
||||
it('should select by attr name case insensitive independent of the value', () => {
|
||||
matcher.addSelectables(s1 = CssSelector.parse('[someAttr]'), 1);
|
||||
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(matcher.match(CssSelector.parse('[SOMEATTR]')[0], selectableCollector)).toEqual(true);
|
||||
expect(matched).toEqual([s1[0],1]);
|
||||
expect(matched).toEqual([s1[0], 1]);
|
||||
|
||||
reset();
|
||||
expect(matcher.match(CssSelector.parse('[SOMEATTR=someValue]')[0], selectableCollector)).toEqual(true);
|
||||
expect(matched).toEqual([s1[0],1]);
|
||||
expect(matcher.match(CssSelector.parse('[SOMEATTR=someValue]')[0], selectableCollector))
|
||||
.toEqual(true);
|
||||
expect(matched).toEqual([s1[0], 1]);
|
||||
|
||||
reset();
|
||||
expect(matcher.match(CssSelector.parse('[someAttr][someAttr2]')[0], selectableCollector)).toEqual(true);
|
||||
expect(matched).toEqual([s1[0],1,s2[0],2]);
|
||||
expect(matcher.match(CssSelector.parse('[someAttr][someAttr2]')[0], selectableCollector))
|
||||
.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', () => {
|
||||
|
@ -74,36 +78,48 @@ export function main() {
|
|||
var empty = DOM.getAttribute(element, 'attr');
|
||||
elementSelector.addAttribute('some-decor', empty);
|
||||
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', () => {
|
||||
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(matcher.match(CssSelector.parse('[SOMEATTR=SOMEVALUE]')[0], selectableCollector)).toEqual(true);
|
||||
expect(matched).toEqual([s1[0],1]);
|
||||
expect(matcher.match(CssSelector.parse('[SOMEATTR=SOMEVALUE]')[0], selectableCollector))
|
||||
.toEqual(true);
|
||||
expect(matched).toEqual([s1[0], 1]);
|
||||
});
|
||||
|
||||
it('should select by element name, class name and attribute name with value', () => {
|
||||
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(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(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(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(matcher.match(CssSelector.parse('someTag.someClass[someAttr=someValue]')[0], selectableCollector)).toEqual(true);
|
||||
expect(matched).toEqual([s1[0],1]);
|
||||
expect(matcher.match(CssSelector.parse('someTag.someClass[someAttr=someValue]')[0],
|
||||
selectableCollector))
|
||||
.toEqual(true);
|
||||
expect(matched).toEqual([s1[0], 1]);
|
||||
});
|
||||
|
||||
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(s4 = CssSelector.parse('.class2.class1'), 4);
|
||||
|
||||
expect(matcher.match(CssSelector.parse('[someAttr].someClass')[0], selectableCollector)).toEqual(true);
|
||||
expect(matched).toEqual([s1[0],1,s2[0],2]);
|
||||
expect(matcher.match(CssSelector.parse('[someAttr].someClass')[0], selectableCollector))
|
||||
.toEqual(true);
|
||||
expect(matched).toEqual([s1[0], 1, s2[0], 2]);
|
||||
|
||||
reset();
|
||||
expect(matcher.match(CssSelector.parse('.someClass[someAttr]')[0], selectableCollector)).toEqual(true);
|
||||
expect(matched).toEqual([s1[0],1,s2[0],2]);
|
||||
expect(matcher.match(CssSelector.parse('.someClass[someAttr]')[0], selectableCollector))
|
||||
.toEqual(true);
|
||||
expect(matched).toEqual([s1[0], 1, s2[0], 2]);
|
||||
|
||||
reset();
|
||||
expect(matcher.match(CssSelector.parse('.class1.class2')[0], selectableCollector)).toEqual(true);
|
||||
expect(matched).toEqual([s3[0],3,s4[0],4]);
|
||||
expect(matcher.match(CssSelector.parse('.class1.class2')[0], selectableCollector))
|
||||
.toEqual(true);
|
||||
expect(matched).toEqual([s3[0], 3, s4[0], 4]);
|
||||
|
||||
reset();
|
||||
expect(matcher.match(CssSelector.parse('.class2.class1')[0], selectableCollector)).toEqual(true);
|
||||
expect(matched).toEqual([s4[0],4,s3[0],3]);
|
||||
expect(matcher.match(CssSelector.parse('.class2.class1')[0], selectableCollector))
|
||||
.toEqual(true);
|
||||
expect(matched).toEqual([s4[0], 4, s3[0], 3]);
|
||||
});
|
||||
|
||||
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[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([]);
|
||||
});
|
||||
|
||||
|
@ -157,27 +178,31 @@ export function main() {
|
|||
matcher.addSelectables(s3 = CssSelector.parse(':not(.someClass)'), 3);
|
||||
matcher.addSelectables(s4 = CssSelector.parse(':not(.someOtherClass[someAttr])'), 4);
|
||||
|
||||
expect(matcher.match(CssSelector.parse('p[someOtherAttr].someOtherClass')[0], selectableCollector)).toEqual(true);
|
||||
expect(matched).toEqual([s1[0],1,s2[0],2,s3[0],3,s4[0],4]);
|
||||
expect(matcher.match(CssSelector.parse('p[someOtherAttr].someOtherClass')[0],
|
||||
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', () => {
|
||||
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(matched).toEqual([s1[1],1]);
|
||||
expect(matcher.match(CssSelector.parse('textbox')[0], selectableCollector)).toEqual(true);
|
||||
expect(matched).toEqual([s1[1], 1]);
|
||||
|
||||
reset();
|
||||
expect(matcher.match(CssSelector.parse('input[type=text]')[0], selectableCollector)).toEqual(true);
|
||||
expect(matched).toEqual([s1[0],1]);
|
||||
reset();
|
||||
expect(matcher.match(CssSelector.parse('input[type=text]')[0], selectableCollector))
|
||||
.toEqual(true);
|
||||
expect(matched).toEqual([s1[0], 1]);
|
||||
});
|
||||
|
||||
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(matched.length).toEqual(2);
|
||||
expect(matched).toEqual([s1[0],1]);
|
||||
expect(matcher.match(CssSelector.parse('input.someclass')[0], selectableCollector))
|
||||
.toEqual(true);
|
||||
expect(matched.length).toEqual(2);
|
||||
expect(matched).toEqual([s1[0], 1]);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -251,9 +276,8 @@ export function main() {
|
|||
});
|
||||
|
||||
it('should throw when nested :not', () => {
|
||||
expect(() => {
|
||||
CssSelector.parse('sometag:not(:not([attrname=attrvalue].someclass))')[0];
|
||||
}).toThrowError('Nesting :not is not allowed in a selector');
|
||||
expect(() => { CssSelector.parse('sometag:not(:not([attrname=attrvalue].someclass))')[0]; })
|
||||
.toThrowError('Nesting :not is not allowed in a selector');
|
||||
});
|
||||
|
||||
it('should detect lists of selectors', () => {
|
||||
|
@ -266,7 +290,8 @@ export function main() {
|
|||
});
|
||||
|
||||
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[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 {Lexer, Parser} from 'angular2/change_detection';
|
||||
import {IgnoreChildrenStep} from './pipeline_spec';
|
||||
import {ElementBinderBuilder} from 'angular2/src/render/dom/view/proto_view_builder';
|
||||
|
||||
export function main() {
|
||||
describe('TextInterpolationParser', () => {
|
||||
function createPipeline() {
|
||||
return new CompilePipeline([
|
||||
new IgnoreChildrenStep(),
|
||||
new TextInterpolationParser(new Parser(new Lexer()))
|
||||
]);
|
||||
return new CompilePipeline(
|
||||
[new IgnoreChildrenStep(), new TextInterpolationParser(new Parser(new Lexer()))]);
|
||||
}
|
||||
|
||||
function process(element) {
|
||||
return ListWrapper.map(
|
||||
createPipeline().process(element),
|
||||
(compileElement) => compileElement.inheritedElementBinder
|
||||
);
|
||||
function process(element): List<ElementBinderBuilder> {
|
||||
return ListWrapper.map(createPipeline().process(element),
|
||||
(compileElement) => compileElement.inheritedElementBinder);
|
||||
}
|
||||
|
||||
function assertTextBinding(elementBinder, bindingIndex, nodeIndex, expression) {
|
|
@ -21,7 +21,8 @@ export function main() {
|
|||
var rootElement = el('<div><template if="true">a</template></div>');
|
||||
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(DOM.getOuterHTML(results[2].element)).toEqual('<template>a</template>');
|
||||
expect(results[2].isViewRoot).toBe(true);
|
||||
|
@ -56,9 +57,11 @@ export function main() {
|
|||
var rootElement = el('<div><template if="true">a</template></div>');
|
||||
var results = createPipeline().process(rootElement);
|
||||
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(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 results = createPipeline().process(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[2].element)).toEqual('<span template=""></span>')
|
||||
expect(DOM.getOuterHTML(results[0].element))
|
||||
.toEqual('<div><template class="ng-binding"></template></div>');
|
||||
expect(DOM.getOuterHTML(results[2].element)).toEqual('<span template=""></span>');
|
||||
expect(results[2].element).toBe(originalChild);
|
||||
});
|
||||
|
||||
|
@ -83,7 +87,8 @@ export function main() {
|
|||
expect(results[0].element).toBe(rootElement);
|
||||
expect(results[0].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);
|
||||
});
|
||||
|
||||
|
@ -96,14 +101,17 @@ export function main() {
|
|||
it('should add property bindings from the template attribute', () => {
|
||||
var rootElement = el('<div><div template="some-prop:expr"></div></div>');
|
||||
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');
|
||||
});
|
||||
|
||||
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 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', () => {
|
||||
|
@ -137,8 +145,10 @@ export function main() {
|
|||
var rootElement = el('<div><span template=""></span></div>');
|
||||
var results = createPipeline().process(rootElement);
|
||||
expect(results[2].inheritedProtoView).not.toBe(null);
|
||||
expect(results[2].inheritedProtoView).toBe(results[1].inheritedElementBinder.nestedProtoView);
|
||||
expect(DOM.getOuterHTML(results[2].inheritedProtoView.rootElement)).toEqual('<span template=""></span>');
|
||||
expect(results[2].inheritedProtoView)
|
||||
.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 results = createPipeline().process(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[2].element)).toEqual('<span *ng-if=""></span>')
|
||||
expect(DOM.getOuterHTML(results[0].element))
|
||||
.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);
|
||||
});
|
||||
|
||||
|
@ -169,21 +180,24 @@ export function main() {
|
|||
expect(results[0].element).toBe(rootElement);
|
||||
expect(results[0].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);
|
||||
});
|
||||
|
||||
it('should add property bindings from the template attribute', () => {
|
||||
var rootElement = el('<div><div *prop="expr"></div></div>');
|
||||
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');
|
||||
});
|
||||
|
||||
it('should add variable mappings from the template attribute to the nestedProtoView', () => {
|
||||
var rootElement = el('<div><div *foreach="var varName=mapName"></div></div>');
|
||||
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', () => {
|
||||
|
@ -217,8 +231,10 @@ export function main() {
|
|||
var rootElement = el('<div><span *foo></span></div>');
|
||||
var results = createPipeline().process(rootElement);
|
||||
expect(results[2].inheritedProtoView).not.toBe(null);
|
||||
expect(results[2].inheritedProtoView).toBe(results[1].inheritedElementBinder.nestedProtoView);
|
||||
expect(DOM.getOuterHTML(results[2].inheritedProtoView.rootElement)).toEqual('<span *foo=""></span>');
|
||||
expect(results[2].inheritedProtoView)
|
||||
.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 {DirectiveMetadata} from 'angular2/src/render/api';
|
||||
import {directiveMetadataFromMap, directiveMetadataToMap} from
|
||||
'angular2/src/render/dom/convert';
|
||||
import {directiveMetadataFromMap, directiveMetadataToMap} from 'angular2/src/render/dom/convert';
|
||||
import {ddescribe, describe, expect, it} from 'angular2/test_lib';
|
||||
|
||||
export function main() {
|
||||
|
@ -10,10 +9,8 @@ export function main() {
|
|||
var someComponent = new DirectiveMetadata({
|
||||
compileChildren: false,
|
||||
hostListeners: MapWrapper.createFromPairs([['listenKey', 'listenVal']]),
|
||||
hostProperties:
|
||||
MapWrapper.createFromPairs([['hostPropKey', 'hostPropVal']]),
|
||||
hostActions:
|
||||
MapWrapper.createFromPairs([['hostActionKey', 'hostActionVal']]),
|
||||
hostProperties: MapWrapper.createFromPairs([['hostPropKey', 'hostPropVal']]),
|
||||
hostActions: MapWrapper.createFromPairs([['hostActionKey', 'hostActionVal']]),
|
||||
id: 'someComponent',
|
||||
properties: MapWrapper.createFromPairs([['propKey', 'propVal']]),
|
||||
readAttributes: ['read1', 'read2'],
|
||||
|
@ -22,29 +19,26 @@ export function main() {
|
|||
});
|
||||
var map = directiveMetadataToMap(someComponent);
|
||||
expect(MapWrapper.get(map, 'compileChildren')).toEqual(false);
|
||||
expect(MapWrapper.get(map, 'hostListeners')).toEqual(
|
||||
MapWrapper.createFromPairs([['listenKey', 'listenVal']]));
|
||||
expect(MapWrapper.get(map, 'hostProperties')).toEqual(
|
||||
MapWrapper.createFromPairs([['hostPropKey', 'hostPropVal']]));
|
||||
expect(MapWrapper.get(map, 'hostActions')).toEqual(
|
||||
MapWrapper.createFromPairs([['hostActionKey', 'hostActionVal']]));
|
||||
expect(MapWrapper.get(map, 'hostListeners'))
|
||||
.toEqual(MapWrapper.createFromPairs([['listenKey', 'listenVal']]));
|
||||
expect(MapWrapper.get(map, 'hostProperties'))
|
||||
.toEqual(MapWrapper.createFromPairs([['hostPropKey', 'hostPropVal']]));
|
||||
expect(MapWrapper.get(map, 'hostActions'))
|
||||
.toEqual(MapWrapper.createFromPairs([['hostActionKey', 'hostActionVal']]));
|
||||
expect(MapWrapper.get(map, 'id')).toEqual('someComponent');
|
||||
expect(MapWrapper.get(map, 'properties')).toEqual(
|
||||
MapWrapper.createFromPairs([['propKey', 'propVal']]));
|
||||
expect(MapWrapper.get(map, 'properties'))
|
||||
.toEqual(MapWrapper.createFromPairs([['propKey', 'propVal']]));
|
||||
expect(MapWrapper.get(map, 'readAttributes')).toEqual(['read1', 'read2']);
|
||||
expect(MapWrapper.get(map, 'selector')).toEqual('some-comp');
|
||||
expect(MapWrapper.get(map, 'type')).toEqual(
|
||||
DirectiveMetadata.COMPONENT_TYPE);
|
||||
expect(MapWrapper.get(map, 'type')).toEqual(DirectiveMetadata.COMPONENT_TYPE);
|
||||
});
|
||||
|
||||
it('mapToDirectiveMetadata', () => {
|
||||
var map = MapWrapper.createFromPairs([
|
||||
['compileChildren', false],
|
||||
['hostListeners', MapWrapper.createFromPairs([['testKey', 'testVal']])],
|
||||
['hostProperties',
|
||||
MapWrapper.createFromPairs([['hostPropKey', 'hostPropVal']])],
|
||||
['hostActions',
|
||||
MapWrapper.createFromPairs([['hostActionKey', 'hostActionVal']])],
|
||||
['hostProperties', MapWrapper.createFromPairs([['hostPropKey', 'hostPropVal']])],
|
||||
['hostActions', MapWrapper.createFromPairs([['hostActionKey', 'hostActionVal']])],
|
||||
['id', 'testId'],
|
||||
['properties', MapWrapper.createFromPairs([['propKey', 'propVal']])],
|
||||
['readAttributes', ['readTest1', 'readTest2']],
|
||||
|
@ -53,15 +47,13 @@ export function main() {
|
|||
]);
|
||||
var meta = directiveMetadataFromMap(map);
|
||||
expect(meta.compileChildren).toEqual(false);
|
||||
expect(meta.hostListeners).toEqual(
|
||||
MapWrapper.createFromPairs([['testKey', 'testVal']]));
|
||||
expect(meta.hostProperties).toEqual(
|
||||
MapWrapper.createFromPairs([['hostPropKey', 'hostPropVal']]));
|
||||
expect(meta.hostActions).toEqual(
|
||||
MapWrapper.createFromPairs([['hostActionKey', 'hostActionVal']]));
|
||||
expect(meta.hostListeners).toEqual(MapWrapper.createFromPairs([['testKey', 'testVal']]));
|
||||
expect(meta.hostProperties)
|
||||
.toEqual(MapWrapper.createFromPairs([['hostPropKey', 'hostPropVal']]));
|
||||
expect(meta.hostActions)
|
||||
.toEqual(MapWrapper.createFromPairs([['hostActionKey', 'hostActionVal']]));
|
||||
expect(meta.id).toEqual('testId');
|
||||
expect(meta.properties).toEqual(
|
||||
MapWrapper.createFromPairs([['propKey', 'propVal']]));
|
||||
expect(meta.properties).toEqual(MapWrapper.createFromPairs([['propKey', 'propVal']]));
|
||||
expect(meta.readAttributes).toEqual(['readTest1', 'readTest2']);
|
||||
expect(meta.selector).toEqual('testSelector');
|
||||
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 {PromiseWrapper, Promise} from 'angular2/src/facade/async';
|
||||
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 {DefaultDomCompiler} from 'angular2/src/render/dom/compiler/compiler';
|
||||
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 {el, dispatchEvent} from 'angular2/test_lib';
|
||||
|
||||
export class TestView {
|
||||
rawView:DomView;
|
||||
viewRef:RenderViewRef;
|
||||
events:List;
|
||||
rawView: DomView;
|
||||
viewRef: RenderViewRef;
|
||||
events: List<List<any>>;
|
||||
|
||||
constructor(viewRef:RenderViewRef) {
|
||||
constructor(viewRef: RenderViewRef) {
|
||||
this.viewRef = viewRef;
|
||||
this.rawView = resolveInternalDomView(viewRef);
|
||||
this.events = [];
|
||||
|
@ -23,17 +29,12 @@ export class TestView {
|
|||
}
|
||||
|
||||
|
||||
@IMPLEMENTS(EventDispatcher)
|
||||
class LoggingEventDispatcher {
|
||||
log:List;
|
||||
class LoggingEventDispatcher implements EventDispatcher {
|
||||
log: List<List<any>>;
|
||||
|
||||
constructor(log:List) {
|
||||
this.log = log;
|
||||
}
|
||||
constructor(log: List<List<any>>) { this.log = log; }
|
||||
|
||||
dispatchEvent(
|
||||
elementIndex:number, eventName:string, locals:Map<string, any>
|
||||
) {
|
||||
dispatchEvent(elementIndex: number, eventName: string, locals: Map<string, any>) {
|
||||
ListWrapper.push(this.log, [elementIndex, eventName, locals]);
|
||||
return true;
|
||||
}
|
||||
|
@ -42,84 +43,87 @@ class LoggingEventDispatcher {
|
|||
|
||||
@Injectable()
|
||||
export class DomTestbed {
|
||||
renderer:DomRenderer;
|
||||
compiler:DefaultDomCompiler;
|
||||
renderer: DomRenderer;
|
||||
compiler: DefaultDomCompiler;
|
||||
rootEl;
|
||||
|
||||
constructor(renderer:DomRenderer, compiler:DefaultDomCompiler, @Inject(DOCUMENT_TOKEN) document) {
|
||||
constructor(renderer: DomRenderer, compiler: DefaultDomCompiler,
|
||||
@Inject(DOCUMENT_TOKEN) document) {
|
||||
this.renderer = renderer;
|
||||
this.compiler = compiler;
|
||||
this.rootEl = el('<div id="root"></div>');
|
||||
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.appendChild(DOM.querySelector(document, 'body'), this.rootEl);
|
||||
}
|
||||
|
||||
compileAll(directivesOrViewDefinitions:List):Promise<List<ProtoViewDto>> {
|
||||
return PromiseWrapper.all(
|
||||
ListWrapper.map(directivesOrViewDefinitions, (entry) => {
|
||||
if (entry instanceof DirectiveMetadata) {
|
||||
return this.compiler.compileHost(entry);
|
||||
} else {
|
||||
return this.compiler.compile(entry);
|
||||
}
|
||||
})
|
||||
);
|
||||
compileAll(directivesOrViewDefinitions: List<DirectiveMetadata |
|
||||
ViewDefinition>): Promise<List<ProtoViewDto>> {
|
||||
return PromiseWrapper.all(ListWrapper.map(directivesOrViewDefinitions, (entry) => {
|
||||
if (entry instanceof DirectiveMetadata) {
|
||||
return this.compiler.compileHost(entry);
|
||||
} else {
|
||||
return this.compiler.compile(entry);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
_createTestView(viewRef:RenderViewRef) {
|
||||
_createTestView(viewRef: RenderViewRef) {
|
||||
var testView = new TestView(viewRef);
|
||||
this.renderer.setEventDispatcher(viewRef, new LoggingEventDispatcher(testView.events));
|
||||
return testView;
|
||||
}
|
||||
|
||||
createRootView(rootProtoView:ProtoViewDto):TestView {
|
||||
createRootView(rootProtoView: ProtoViewDto): TestView {
|
||||
var viewRef = this.renderer.createRootHostView(rootProtoView.render, '#root');
|
||||
this.renderer.hydrateView(viewRef);
|
||||
return this._createTestView(viewRef);
|
||||
}
|
||||
|
||||
createComponentView(parentViewRef:RenderViewRef, boundElementIndex:number, componentProtoView:ProtoViewDto):TestView {
|
||||
createComponentView(parentViewRef: RenderViewRef, boundElementIndex: number,
|
||||
componentProtoView: ProtoViewDto): TestView {
|
||||
var componentViewRef = this.renderer.createView(componentProtoView.render);
|
||||
this.renderer.attachComponentView(parentViewRef, boundElementIndex, componentViewRef);
|
||||
this.renderer.hydrateView(componentViewRef);
|
||||
return this._createTestView(componentViewRef);
|
||||
}
|
||||
|
||||
createRootViews(protoViews:List<ProtoViewDto>):List<TestView> {
|
||||
createRootViews(protoViews: List<ProtoViewDto>): List<TestView> {
|
||||
var views = [];
|
||||
var lastView = this.createRootView(protoViews[0]);
|
||||
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]);
|
||||
ListWrapper.push(views, lastView);
|
||||
}
|
||||
return views;
|
||||
}
|
||||
|
||||
destroyComponentView(parentViewRef:RenderViewRef, boundElementIndex:number, componentView:RenderViewRef) {
|
||||
destroyComponentView(parentViewRef: RenderViewRef, boundElementIndex: number,
|
||||
componentView: RenderViewRef) {
|
||||
this.renderer.dehydrateView(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);
|
||||
this.renderer.attachViewInContainer(parentViewRef, boundElementIndex, atIndex, viewRef);
|
||||
this.renderer.hydrateView(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.detachViewInContainer(parentViewRef, boundElementIndex, atIndex, 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];
|
||||
dispatchEvent(element, eventName);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,19 @@
|
|||
import {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 {
|
||||
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 {List, ListWrapper, Map, MapWrapper} from 'angular2/src/facade/collection';
|
||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||
|
@ -7,9 +21,7 @@ import {DOM} from 'angular2/src/dom/dom_adapter';
|
|||
export function main() {
|
||||
var domEventPlugin;
|
||||
|
||||
beforeEach(() => {
|
||||
domEventPlugin = new DomEventsPlugin();
|
||||
});
|
||||
beforeEach(() => { domEventPlugin = new DomEventsPlugin(); });
|
||||
|
||||
describe('EventManager', () => {
|
||||
|
||||
|
@ -35,7 +47,7 @@ export function main() {
|
|||
var element = el('<div></div>');
|
||||
var clickHandler = (e) => e;
|
||||
var dblClickHandler = (e) => e;
|
||||
var plugin1= new FakeEventManagerPlugin(['dblclick']);
|
||||
var plugin1 = new FakeEventManagerPlugin(['dblclick']);
|
||||
var plugin2 = new FakeEventManagerPlugin(['click', 'dblclick']);
|
||||
var manager = new EventManager([plugin1, plugin2], new FakeNgZone());
|
||||
manager.addEventListener(element, 'click', clickHandler);
|
||||
|
@ -51,7 +63,7 @@ export function main() {
|
|||
var plugin = new FakeEventManagerPlugin(['dblclick']);
|
||||
var manager = new EventManager([plugin], new FakeNgZone());
|
||||
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', () => {
|
||||
|
@ -109,8 +121,8 @@ export function main() {
|
|||
|
||||
class FakeEventManagerPlugin extends EventManagerPlugin {
|
||||
_supports: List<string>;
|
||||
_nonBubbleEventHandlers: Map;
|
||||
_bubbleEventHandlers: Map;
|
||||
_nonBubbleEventHandlers: Map<string, Function>;
|
||||
_bubbleEventHandlers: Map<string, Function>;
|
||||
constructor(supports: List<string>) {
|
||||
super();
|
||||
this._supports = supports;
|
||||
|
@ -118,28 +130,22 @@ class FakeEventManagerPlugin extends EventManagerPlugin {
|
|||
this._bubbleEventHandlers = MapWrapper.create();
|
||||
}
|
||||
|
||||
supports(eventName: string): boolean {
|
||||
return ListWrapper.contains(this._supports, eventName);
|
||||
}
|
||||
supports(eventName: string): boolean { return ListWrapper.contains(this._supports, eventName); }
|
||||
|
||||
addEventListener(element, eventName: string, handler: Function, shouldSupportBubble: boolean) {
|
||||
MapWrapper.set(shouldSupportBubble ? this._bubbleEventHandlers : this._nonBubbleEventHandlers,
|
||||
eventName, handler);
|
||||
return () => {MapWrapper.delete(shouldSupportBubble ? this._bubbleEventHandlers : this._nonBubbleEventHandlers,
|
||||
eventName)};
|
||||
eventName, handler);
|
||||
return () => {
|
||||
MapWrapper.delete(
|
||||
shouldSupportBubble ? this._bubbleEventHandlers : this._nonBubbleEventHandlers, eventName)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class FakeNgZone extends NgZone {
|
||||
constructor() {
|
||||
super({enableLongStackTrace: false});
|
||||
}
|
||||
constructor() { super({enableLongStackTrace: false}); }
|
||||
|
||||
run(fn) {
|
||||
fn();
|
||||
}
|
||||
run(fn) { fn(); }
|
||||
|
||||
runOutsideAngular(fn) {
|
||||
return fn();
|
||||
}
|
||||
runOutsideAngular(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';
|
||||
|
||||
export function main() {
|
||||
|
@ -15,53 +25,33 @@ export function main() {
|
|||
|
||||
it('should correctly parse event names', () => {
|
||||
// key with no modifier
|
||||
expect(KeyEventsPlugin.parseEventName('keydown.enter')).toEqual({
|
||||
'domEventName': 'keydown',
|
||||
'fullKey': 'enter'
|
||||
});
|
||||
expect(KeyEventsPlugin.parseEventName('keyup.enter')).toEqual({
|
||||
'domEventName': 'keyup',
|
||||
'fullKey': 'enter'
|
||||
});
|
||||
expect(KeyEventsPlugin.parseEventName('keydown.enter'))
|
||||
.toEqual({'domEventName': 'keydown', 'fullKey': 'enter'});
|
||||
expect(KeyEventsPlugin.parseEventName('keyup.enter'))
|
||||
.toEqual({'domEventName': 'keyup', 'fullKey': 'enter'});
|
||||
|
||||
// key with modifiers:
|
||||
expect(KeyEventsPlugin.parseEventName('keydown.control.shift.enter')).toEqual({
|
||||
'domEventName': 'keydown',
|
||||
'fullKey': 'control.shift.enter'
|
||||
});
|
||||
expect(KeyEventsPlugin.parseEventName('keyup.control.shift.enter')).toEqual({
|
||||
'domEventName': 'keyup',
|
||||
'fullKey': 'control.shift.enter'
|
||||
});
|
||||
expect(KeyEventsPlugin.parseEventName('keydown.control.shift.enter'))
|
||||
.toEqual({'domEventName': 'keydown', '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:
|
||||
expect(KeyEventsPlugin.parseEventName('keydown.shift.control.enter')).toEqual({
|
||||
'domEventName': 'keydown',
|
||||
'fullKey': 'control.shift.enter'
|
||||
});
|
||||
expect(KeyEventsPlugin.parseEventName('keyup.shift.control.enter')).toEqual({
|
||||
'domEventName': 'keyup',
|
||||
'fullKey': 'control.shift.enter'
|
||||
});
|
||||
expect(KeyEventsPlugin.parseEventName('keydown.shift.control.enter'))
|
||||
.toEqual({'domEventName': 'keydown', 'fullKey': 'control.shift.enter'});
|
||||
expect(KeyEventsPlugin.parseEventName('keyup.shift.control.enter'))
|
||||
.toEqual({'domEventName': 'keyup', 'fullKey': 'control.shift.enter'});
|
||||
|
||||
// key that is also a modifier:
|
||||
expect(KeyEventsPlugin.parseEventName('keydown.shift.control')).toEqual({
|
||||
'domEventName': 'keydown',
|
||||
'fullKey': 'shift.control'
|
||||
});
|
||||
expect(KeyEventsPlugin.parseEventName('keyup.shift.control')).toEqual({
|
||||
'domEventName': 'keyup',
|
||||
'fullKey': 'shift.control'
|
||||
});
|
||||
expect(KeyEventsPlugin.parseEventName('keydown.shift.control'))
|
||||
.toEqual({'domEventName': 'keydown', 'fullKey': 'shift.control'});
|
||||
expect(KeyEventsPlugin.parseEventName('keyup.shift.control'))
|
||||
.toEqual({'domEventName': 'keyup', 'fullKey': 'shift.control'});
|
||||
|
||||
expect(KeyEventsPlugin.parseEventName('keydown.control.shift')).toEqual({
|
||||
'domEventName': 'keydown',
|
||||
'fullKey': 'control.shift'
|
||||
});
|
||||
expect(KeyEventsPlugin.parseEventName('keyup.control.shift')).toEqual({
|
||||
'domEventName': 'keyup',
|
||||
'fullKey': 'control.shift'
|
||||
});
|
||||
expect(KeyEventsPlugin.parseEventName('keydown.control.shift'))
|
||||
.toEqual({'domEventName': 'keydown', '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 {IMPLEMENTS} from 'angular2/src/facade/lang';
|
||||
import {
|
||||
describe,
|
||||
beforeEach,
|
||||
it,
|
||||
expect,
|
||||
ddescribe,
|
||||
iit,
|
||||
SpyObject,
|
||||
el,
|
||||
proxy
|
||||
} from 'angular2/test_lib';
|
||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||
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 _scriptEnd = `<script end=""></script>`;
|
||||
|
@ -26,7 +30,8 @@ export function main() {
|
|||
c.init(null);
|
||||
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", () => {
|
|
@ -51,9 +51,9 @@ export function main() {
|
|||
it('should rewrite style urls', () => {
|
||||
var styleElement = el('<style>.foo {background-image: url("img.jpg");}</style>');
|
||||
strategy.processStyleElement('someComponent', 'http://base', styleElement);
|
||||
expect(styleElement).toHaveText(".foo[_ngcontent-0] {\n" +
|
||||
"background-image: url(http://base/img.jpg);\n" +
|
||||
"}");
|
||||
expect(styleElement)
|
||||
.toHaveText(".foo[_ngcontent-0] {\n" + "background-image: url(http://base/img.jpg);\n" +
|
||||
"}");
|
||||
});
|
||||
|
||||
it('should scope styles', () => {
|
||||
|
@ -63,18 +63,19 @@ export function main() {
|
|||
});
|
||||
|
||||
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 stylePromise = strategy.processStyleElement('someComponent', 'http://base', styleElement);
|
||||
expect(stylePromise).toBePromise();
|
||||
expect(styleElement).toHaveText('');
|
||||
var styleElement = el('<style>@import "one.css";</style>');
|
||||
var stylePromise =
|
||||
strategy.processStyleElement('someComponent', 'http://base', styleElement);
|
||||
expect(stylePromise).toBePromise();
|
||||
expect(styleElement).toHaveText('');
|
||||
|
||||
stylePromise.then((_) => {
|
||||
expect(styleElement).toHaveText('.one[_ngcontent-0] {\n\n}');
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
stylePromise.then((_) => {
|
||||
expect(styleElement).toHaveText('.one[_ngcontent-0] {\n\n}');
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should return the same style given the same component', () => {
|
||||
var styleElement = el('<style>.foo {} :host {}</style>');
|
||||
|
@ -121,7 +122,7 @@ export function main() {
|
|||
}
|
||||
|
||||
class FakeXHR extends XHR {
|
||||
_responses: Map;
|
||||
_responses: Map<string, string>;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
@ -137,7 +138,5 @@ class FakeXHR extends XHR {
|
|||
return PromiseWrapper.resolve(response);
|
||||
}
|
||||
|
||||
reply(url: string, response: string) {
|
||||
MapWrapper.set(this._responses, url, response);
|
||||
}
|
||||
reply(url: string, response: string) { MapWrapper.set(this._responses, url, response); }
|
||||
}
|
|
@ -46,13 +46,12 @@ export function main() {
|
|||
it('should rewrite style urls', () => {
|
||||
var styleElement = el('<style>.foo {background-image: url("img.jpg");}</style>');
|
||||
strategy.processStyleElement('someComponent', 'http://base', styleElement);
|
||||
expect(styleElement).toHaveText(".foo {" +
|
||||
"background-image: url('http://base/img.jpg');" +
|
||||
"}");
|
||||
expect(styleElement)
|
||||
.toHaveText(".foo {" + "background-image: url('http://base/img.jpg');" + "}");
|
||||
});
|
||||
|
||||
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);
|
||||
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 {ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
|
||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||
|
@ -9,12 +19,13 @@ import {DomViewContainer} from 'angular2/src/render/dom/view/view_container';
|
|||
|
||||
@proxy
|
||||
@IMPLEMENTS(DomView)
|
||||
class FakeView {
|
||||
class FakeView extends SpyObject {
|
||||
boundElements;
|
||||
contentTags;
|
||||
viewContainers;
|
||||
|
||||
constructor(containers = null) {
|
||||
super(DomView);
|
||||
this.boundElements = [];
|
||||
this.contentTags = [];
|
||||
this.viewContainers = [];
|
||||
|
@ -38,62 +49,50 @@ class FakeView {
|
|||
}
|
||||
}
|
||||
|
||||
noSuchMethod(i) {
|
||||
super.noSuchMethod(i);
|
||||
}
|
||||
noSuchMethod(i) { super.noSuchMethod(i); }
|
||||
}
|
||||
|
||||
@proxy
|
||||
@IMPLEMENTS(DomViewContainer)
|
||||
class FakeViewContainer {
|
||||
class FakeViewContainer extends SpyObject {
|
||||
_nodes;
|
||||
_contentTagContainers;
|
||||
templateElement;
|
||||
|
||||
constructor(templateEl, nodes = null, views = null) {
|
||||
super(DomViewContainer);
|
||||
this.templateElement = templateEl;
|
||||
this._nodes = nodes;
|
||||
this._contentTagContainers = views;
|
||||
}
|
||||
|
||||
nodes(){
|
||||
return this._nodes;
|
||||
}
|
||||
nodes() { return this._nodes; }
|
||||
|
||||
contentTagContainers(){
|
||||
return this._contentTagContainers;
|
||||
}
|
||||
contentTagContainers() { return this._contentTagContainers; }
|
||||
|
||||
noSuchMethod(i) {
|
||||
super.noSuchMethod(i);
|
||||
}
|
||||
noSuchMethod(i) { super.noSuchMethod(i); }
|
||||
}
|
||||
|
||||
|
||||
@proxy
|
||||
@IMPLEMENTS(Content)
|
||||
class FakeContentTag {
|
||||
class FakeContentTag extends SpyObject {
|
||||
select;
|
||||
_nodes;
|
||||
contentStartElement;
|
||||
|
||||
constructor(contentEl, select = '', nodes = null) {
|
||||
super(Content);
|
||||
this.contentStartElement = contentEl;
|
||||
this.select = select;
|
||||
this._nodes = nodes;
|
||||
}
|
||||
|
||||
insert(nodes){
|
||||
this._nodes = nodes;
|
||||
}
|
||||
insert(nodes) { this._nodes = nodes; }
|
||||
|
||||
nodes() {
|
||||
return this._nodes;
|
||||
}
|
||||
nodes() { return this._nodes; }
|
||||
|
||||
noSuchMethod(i) {
|
||||
super.noSuchMethod(i);
|
||||
}
|
||||
noSuchMethod(i) { super.noSuchMethod(i); }
|
||||
}
|
||||
|
||||
function createLightDom(hostView, shadowView, el) {
|
||||
|
@ -106,29 +105,23 @@ export function main() {
|
|||
describe('LightDom', function() {
|
||||
var lightDomView;
|
||||
|
||||
beforeEach(() => {
|
||||
lightDomView = new FakeView();
|
||||
});
|
||||
beforeEach(() => { lightDomView = new FakeView(); });
|
||||
|
||||
describe("contentTags", () => {
|
||||
it("should collect content tags from element injectors", () => {
|
||||
var tag = new FakeContentTag(el('<script></script>'));
|
||||
var shadowDomView = new FakeView([tag]);
|
||||
|
||||
var lightDom = createLightDom(lightDomView, shadowDomView,
|
||||
el("<div></div>"));
|
||||
var lightDom = createLightDom(lightDomView, shadowDomView, el("<div></div>"));
|
||||
|
||||
expect(lightDom.contentTags()).toEqual([tag]);
|
||||
});
|
||||
|
||||
it("should collect content tags from ViewContainers", () => {
|
||||
var tag = new FakeContentTag(el('<script></script>'));
|
||||
var vc = new FakeViewContainer(null, null, [
|
||||
new FakeView([tag])
|
||||
]);
|
||||
var vc = new FakeViewContainer(null, null, [new FakeView([tag])]);
|
||||
var shadowDomView = new FakeView([vc]);
|
||||
var lightDom = createLightDom(lightDomView, shadowDomView,
|
||||
el("<div></div>"));
|
||||
var lightDom = createLightDom(lightDomView, shadowDomView, el("<div></div>"));
|
||||
|
||||
expect(lightDom.contentTags()).toEqual([tag]);
|
||||
});
|
||||
|
@ -136,7 +129,7 @@ export function main() {
|
|||
|
||||
describe("expandedDomNodes", () => {
|
||||
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);
|
||||
expect(toHtml(lightDom.expandedDomNodes())).toEqual(["<a></a>"]);
|
||||
});
|
||||
|
@ -144,14 +137,11 @@ export function main() {
|
|||
it("should include view container nodes", () => {
|
||||
var lightDomEl = el("<div><template></template></div>");
|
||||
var lightDom = createLightDom(
|
||||
new FakeView([
|
||||
new FakeViewContainer(
|
||||
DOM.firstChild(lightDomEl), // template element
|
||||
[el('<a></a>')] // light DOM nodes of view container
|
||||
)
|
||||
]),
|
||||
null,
|
||||
lightDomEl);
|
||||
new FakeView(
|
||||
[new FakeViewContainer(DOM.firstChild(lightDomEl), // template element
|
||||
[el('<a></a>')] // light DOM nodes of view container
|
||||
)]),
|
||||
null, lightDomEl);
|
||||
|
||||
expect(toHtml(lightDom.expandedDomNodes())).toEqual(["<a></a>"]);
|
||||
});
|
||||
|
@ -159,15 +149,11 @@ export function main() {
|
|||
it("should include content nodes", () => {
|
||||
var lightDomEl = el("<div><content></content></div>");
|
||||
var lightDom = createLightDom(
|
||||
new FakeView([
|
||||
new FakeContentTag(
|
||||
DOM.firstChild(lightDomEl), // content element
|
||||
'', // selector
|
||||
[el('<a></a>')] // light DOM nodes of content tag
|
||||
)
|
||||
]),
|
||||
null,
|
||||
lightDomEl);
|
||||
new FakeView([new FakeContentTag(DOM.firstChild(lightDomEl), // content element
|
||||
'', // selector
|
||||
[el('<a></a>')] // light DOM nodes of content tag
|
||||
)]),
|
||||
null, lightDomEl);
|
||||
|
||||
expect(toHtml(lightDom.expandedDomNodes())).toEqual(["<a></a>"]);
|
||||
});
|
||||
|
@ -175,12 +161,9 @@ export function main() {
|
|||
it("should work when the element injector array contains nulls", () => {
|
||||
var lightDomEl = el("<div><a></a></div>")
|
||||
|
||||
var lightDomView = new FakeView();
|
||||
var lightDomView = new FakeView();
|
||||
|
||||
var lightDom = createLightDom(
|
||||
lightDomView,
|
||||
new FakeView(),
|
||||
lightDomEl);
|
||||
var lightDom = createLightDom(lightDomView, new FakeView(), lightDomEl);
|
||||
|
||||
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 lightDom = createLightDom(lightDomView, new FakeView([
|
||||
contentA,
|
||||
contentB
|
||||
]), lightDomEl);
|
||||
var lightDom =
|
||||
createLightDom(lightDomView, new FakeView([contentA, contentB]), lightDomEl);
|
||||
|
||||
lightDom.redistribute();
|
||||
|
||||
|
@ -210,10 +191,8 @@ export function main() {
|
|||
|
||||
var lightDomEl = el("<div><a>1</a><b>2</b><a>3</a></div>")
|
||||
|
||||
var lightDom = createLightDom(lightDomView, new FakeView([
|
||||
wildcard,
|
||||
contentB
|
||||
]), lightDomEl);
|
||||
var lightDom =
|
||||
createLightDom(lightDomView, new FakeView([wildcard, contentB]), lightDomEl);
|
||||
|
||||
lightDom.redistribute();
|
||||
|
||||
|
@ -224,7 +203,7 @@ export function main() {
|
|||
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 lightDom = createLightDom(lightDomView, new FakeView([]), lightDomEl);
|
||||
var lightDom = createLightDom(lightDomView, new FakeView([]), lightDomEl);
|
||||
|
||||
lightDom.redistribute();
|
||||
|
||||
|
@ -235,9 +214,8 @@ export function main() {
|
|||
var lightDomEl = el("<div><a>1</a><b>2</b><a>3</a></div>");
|
||||
var bNode = DOM.childNodes(lightDomEl)[1];
|
||||
|
||||
var lightDom = createLightDom(lightDomView, new FakeView([
|
||||
new FakeContentTag(null, "a")
|
||||
]), lightDomEl);
|
||||
var lightDom =
|
||||
createLightDom(lightDomView, new FakeView([new FakeContentTag(null, "a")]), lightDomEl);
|
||||
|
||||
lightDom.redistribute();
|
||||
|
|
@ -40,13 +40,12 @@ export function main() {
|
|||
it('should rewrite style urls', () => {
|
||||
var styleElement = el('<style>.foo {background-image: url("img.jpg");}</style>');
|
||||
strategy.processStyleElement('someComponent', 'http://base', styleElement);
|
||||
expect(styleElement).toHaveText(".foo {" +
|
||||
"background-image: url('http://base/img.jpg');" +
|
||||
"}");
|
||||
expect(styleElement)
|
||||
.toHaveText(".foo {" + "background-image: url('http://base/img.jpg');" + "}");
|
||||
});
|
||||
|
||||
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);
|
||||
expect(styleElement).toHaveText("@import 'http://base/other.css';");
|
||||
});
|
|
@ -6,16 +6,14 @@ import {RegExpWrapper, StringWrapper} from 'angular2/src/facade/lang';
|
|||
export function main() {
|
||||
describe('ShadowCss', function() {
|
||||
|
||||
function s(css: string, contentAttr:string, hostAttr:string = '') {
|
||||
function s(css: string, contentAttr: string, hostAttr: string = '') {
|
||||
var shadowCss = new ShadowCss();
|
||||
var shim = shadowCss.shimCssText(css, contentAttr, hostAttr);
|
||||
var nlRegexp = RegExpWrapper.create('\\n');
|
||||
return StringWrapper.replaceAll(shim, nlRegexp, '');
|
||||
}
|
||||
|
||||
it('should handle empty string', () => {
|
||||
expect(s('', 'a')).toEqual('');
|
||||
});
|
||||
it('should handle empty string', () => { expect(s('', 'a')).toEqual(''); });
|
||||
|
||||
it('should add an attribute to every rule', () => {
|
||||
var css = 'one {color: red;}two {color: red;}';
|
||||
|
@ -67,12 +65,14 @@ export function main() {
|
|||
it('should handle :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) > .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', () => {
|
||||
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', () => {
|
|
@ -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 {
|
||||
resolve(baseUrl: string, url: string): string {
|
||||
return baseUrl + '/' + url;
|
||||
}
|
||||
resolve(baseUrl: string, url: string): string { 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 {DOM} from 'angular2/src/dom/dom_adapter';
|
||||
|
||||
export function main() {
|
||||
var div;
|
||||
beforeEach( () => {
|
||||
div = el('<div></div>');
|
||||
});
|
||||
beforeEach(() => { div = el('<div></div>'); });
|
||||
describe('property setter factory', () => {
|
||||
|
||||
it('should return a setter for a property', () => {
|
||||
|
@ -24,9 +32,8 @@ export function main() {
|
|||
expect(DOM.getAttribute(div, 'role')).toEqual('button');
|
||||
setterFn(div, null);
|
||||
expect(DOM.getAttribute(div, 'role')).toEqual(null);
|
||||
expect(() => {
|
||||
setterFn(div, 4);
|
||||
}).toThrowError("Invalid role attribute, only string values are allowed, got '4'");
|
||||
expect(() => { setterFn(div, 4); })
|
||||
.toThrowError("Invalid role attribute, only string values are allowed, got '4'");
|
||||
|
||||
var otherSetterFn = setterFactory('attr.role');
|
||||
expect(setterFn).toBe(otherSetterFn);
|
|
@ -12,7 +12,8 @@ import {
|
|||
beforeEachBindings,
|
||||
it,
|
||||
xit,
|
||||
SpyObject, proxy
|
||||
SpyObject,
|
||||
proxy
|
||||
} from 'angular2/test_lib';
|
||||
import {IMPLEMENTS, isBlank} from 'angular2/src/facade/lang';
|
||||
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';
|
||||
|
||||
export function main() {
|
||||
|
||||
describe('DomView', () => {
|
||||
function createProtoView(binders = null) {
|
||||
if (isBlank(binders)) {
|
||||
binders = [];
|
||||
}
|
||||
var rootEl = el('<div></div>');
|
||||
return new DomProtoView({
|
||||
element: rootEl,
|
||||
elementBinders: binders
|
||||
});
|
||||
return new DomProtoView({element: rootEl, elementBinders: binders});
|
||||
}
|
||||
|
||||
function createView(pv=null, boundElementCount=0) {
|
||||
function createView(pv = null, boundElementCount = 0) {
|
||||
if (isBlank(pv)) {
|
||||
pv = createProtoView();
|
||||
}
|
||||
var root = el('<div><div></div></div>');
|
||||
var boundElements = [];
|
||||
for (var i=0; i<boundElementCount; i++) {
|
||||
for (var i = 0; i < boundElementCount; i++) {
|
||||
ListWrapper.push(boundElements, el('<span></span'));
|
||||
}
|
||||
return new DomView(pv, [DOM.childNodes(root)[0]],
|
||||
[], boundElements, []);
|
||||
return new DomView(pv, [DOM.childNodes(root)[0]], [], boundElements, []);
|
||||
}
|
||||
|
||||
describe('getDirectParentLightDom', () => {
|
||||
|
||||
it('should return the LightDom of the direct parent', () => {
|
||||
var pv = createProtoView(
|
||||
[new ElementBinder(), new ElementBinder({
|
||||
parentIndex: 0,
|
||||
distanceToParent: 1
|
||||
})]
|
||||
);
|
||||
[new ElementBinder(), new ElementBinder({parentIndex: 0, distanceToParent: 1})]);
|
||||
var view = createView(pv, 2);
|
||||
view.lightDoms[0] = new SpyLightDom();
|
||||
view.lightDoms[1] = new SpyLightDom();
|
||||
view.lightDoms[0] = <any>new SpyLightDom();
|
||||
view.lightDoms[1] = <any>new SpyLightDom();
|
||||
expect(view.getDirectParentLightDom(1)).toBe(view.lightDoms[0]);
|
||||
});
|
||||
|
||||
it('should return null if the direct parent is not bound', () => {
|
||||
var pv = createProtoView(
|
||||
[new ElementBinder(), new ElementBinder(), new ElementBinder({
|
||||
parentIndex: 0,
|
||||
distanceToParent: 2
|
||||
})]
|
||||
);
|
||||
var pv = createProtoView([
|
||||
new ElementBinder(),
|
||||
new ElementBinder(),
|
||||
new ElementBinder({parentIndex: 0, distanceToParent: 2})
|
||||
]);
|
||||
var view = createView(pv, 3);
|
||||
view.lightDoms[0] = new SpyLightDom();
|
||||
view.lightDoms[1] = new SpyLightDom();
|
||||
view.lightDoms[2] = new SpyLightDom();
|
||||
view.lightDoms[0] = <any>new SpyLightDom();
|
||||
view.lightDoms[1] = <any>new SpyLightDom();
|
||||
view.lightDoms[2] = <any>new SpyLightDom();
|
||||
expect(view.getDirectParentLightDom(2)).toBe(null);
|
||||
});
|
||||
|
||||
|
@ -87,7 +78,6 @@ export function main() {
|
|||
@proxy
|
||||
@IMPLEMENTS(LightDom)
|
||||
class SpyLightDom extends SpyObject {
|
||||
constructor(){super(LightDom);}
|
||||
noSuchMethod(m){return super.noSuchMethod(m)}
|
||||
constructor() { super(LightDom); }
|
||||
noSuchMethod(m) { return super.noSuchMethod(m) }
|
||||
}
|
||||
|
Loading…
Reference in New Issue