feat(tests): add a test injector

fixes #614

Asynchronous test should inject an AsyncTestCompleter:

Before:

  it("async test", (done) => {
    // ...
    done();
  });

After:

  it("async test", inject([AsyncTestCompleter], (async) => {
    // ...
    async.done();
  }));

Note: inject() is currently a function and the first parameter is the
array of DI tokens to inject as the test function parameters. This
construct is linked to Traceur limitations. The planned syntax is:

  it("async test", @Inject (async: AsyncTestCompleter) => {
    // ...
    async.done();
  });
This commit is contained in:
Victor Berchet
2015-03-13 11:10:11 +01:00
parent 5926d2e2f7
commit 33b5ba863e
29 changed files with 1241 additions and 640 deletions

View File

@ -1,4 +1,15 @@
import {describe, beforeEach, it, expect, ddescribe, iit, el, IS_DARTIUM} from 'angular2/test_lib';
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';
@ -51,7 +62,7 @@ export function runCompilerCommonTests() {
urlResolver, new ComponentUrlMapper());
}
it('should run the steps and return the ProtoView of the root element', (done) => {
it('should run the steps and return the ProtoView of the root element', inject([AsyncTestCompleter], (async) => {
var rootProtoView = new ProtoView(null, null, null);
var compiler = createCompiler( (parent, current, control) => {
current.inheritedProtoView = rootProtoView;
@ -59,21 +70,21 @@ export function runCompilerCommonTests() {
tplResolver.setTemplate(MainComponent, new Template({inline: '<div></div>'}));
compiler.compile(MainComponent).then( (protoView) => {
expect(protoView).toBe(rootProtoView);
done();
async.done();
});
});
}));
it('should use the inline template', (done) => {
it('should use the inline template', inject([AsyncTestCompleter], (async) => {
var compiler = createCompiler( (parent, current, control) => {
current.inheritedProtoView = new ProtoView(current.element, null, null);
});
compiler.compile(MainComponent).then( (protoView) => {
expect(DOM.getInnerHTML(protoView.element)).toEqual('inline component');
done();
async.done();
});
});
}));
it('should wait for async styles to be resolved', (done) => {
it('should wait for async styles to be resolved', inject([AsyncTestCompleter], (async) => {
var styleResolved = false;
var completer = PromiseWrapper.completer();
@ -95,11 +106,11 @@ export function runCompilerCommonTests() {
completer.resolve(null);
pvPromise.then((protoView) => {
expect(styleResolved).toEqual(true);
done();
async.done();
});
});
}));
it('should load nested components', (done) => {
it('should load nested components', inject([AsyncTestCompleter], (async) => {
var compiler = createCompiler( (parent, current, control) => {
if (DOM.hasClass(current.element, 'nested')) {
current.componentDirective = reader.read(NestedComponent);
@ -113,11 +124,11 @@ export function runCompilerCommonTests() {
compiler.compile(MainComponent).then( (protoView) => {
var nestedView = protoView.elementBinders[0].nestedProtoView;
expect(DOM.getInnerHTML(nestedView.element)).toEqual('nested component');
done();
async.done();
});
});
}));
it('should cache compiled components', (done) => {
it('should cache compiled components', inject([AsyncTestCompleter], (async) => {
var compiler = createCompiler( (parent, current, control) => {
current.inheritedProtoView = new ProtoView(current.element, null, null);
});
@ -128,11 +139,11 @@ export function runCompilerCommonTests() {
return compiler.compile(MainComponent);
}).then( (protoView) => {
expect(firstProtoView).toBe(protoView);
done();
async.done();
});
});
}));
it('should re-use components being compiled', (done) => {
it('should re-use components being compiled', inject([AsyncTestCompleter], (async) => {
var nestedElBinders = [];
var compiler = createCompiler( (parent, current, control) => {
current.inheritedProtoView = new ProtoView(current.element, null, null);
@ -146,11 +157,11 @@ export function runCompilerCommonTests() {
new Template({inline: '<div><div class="nested"></div><div class="nested"></div></div>'}));
compiler.compile(MainComponent).then( (protoView) => {
expect(nestedElBinders[0].nestedProtoView).toBe(nestedElBinders[1].nestedProtoView);
done();
async.done();
});
});
}));
it('should allow recursive components', (done) => {
it('should allow recursive components', inject([AsyncTestCompleter], (async) => {
var compiler = createCompiler( (parent, current, control) => {
current.inheritedProtoView = new ProtoView(current.element, null, null);
current.inheritedElementBinder = current.inheritedProtoView.bindElement(null);
@ -158,9 +169,9 @@ export function runCompilerCommonTests() {
});
compiler.compile(RecursiveComponent).then( (protoView) => {
expect(protoView.elementBinders[0].nestedProtoView).toBe(protoView);
done();
async.done();
});
});
}));
});
});
@ -176,7 +187,7 @@ export function runCompilerCommonTests() {
}
function createNestedComponentSpec(name, resolver: TemplateResolver, error:string = null) {
it(`should load nested components ${name}`, (done) => {
it(`should load nested components ${name}`, inject([AsyncTestCompleter], (async) => {
var compiler = createCompiler((parent, current, control) => {
if (DOM.hasClass(current.element, 'parent')) {
@ -193,14 +204,14 @@ export function runCompilerCommonTests() {
var nestedView = protoView.elementBinders[0].nestedProtoView;
expect(error).toBeNull();
expect(DOM.getInnerHTML(nestedView.element)).toEqual('nested component');
done();
async.done();
},
function(compileError) {
expect(compileError.message).toEqual(error);
done();
async.done();
}
);
});
}));
}
var templateResolver = new FakeTemplateResolver();
@ -244,7 +255,7 @@ export function runCompilerCommonTests() {
});
describe('URL resolution', () => {
it('should resolve template URLs by combining application, component and template URLs', (done) => {
it('should resolve template URLs by combining application, component and template URLs', inject([AsyncTestCompleter], (async) => {
var steps = [new MockStep((parent, current, control) => {
current.inheritedProtoView = new ProtoView(current.element, null, null);
})];
@ -263,9 +274,9 @@ export function runCompilerCommonTests() {
tplResolver.setTemplate(MainComponent, template);
compiler.compile(MainComponent).then((protoView) => {
expect(tplLoader.getTemplateUrl(template)).toEqual('http://www.app.com/cmp/tpl.html');
done();
async.done();
});
})
}))
});
});
}

View File

@ -1,9 +1,11 @@
library angular2.compiler.html5lib_dom_adapter.test;
import 'package:angular2/src/dom/html5lib_adapter.dart';
import 'package:angular2/src/test_lib/test_lib.dart' show testSetup;
import 'compiler_common_tests.dart';
void main() {
Html5LibDomAdapter.makeCurrent();
testSetup();
runCompilerCommonTests();
}

View File

@ -1,4 +1,15 @@
import {describe, xit, it, expect, beforeEach, ddescribe, iit, el} from 'angular2/test_lib';
import {
AsyncTestCompleter,
beforeEach,
ddescribe,
describe,
el,
expect,
iit,
inject,
it,
xit,
} from 'angular2/test_lib';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {Type, isPresent, BaseException, assertionsEnabled, isJsObject} from 'angular2/src/facade/lang';
@ -61,7 +72,7 @@ export function main() {
cd = view.changeDetector;
}
it('should consume text node changes', (done) => {
it('should consume text node changes', inject([AsyncTestCompleter], (async) => {
tplResolver.setTemplate(MyComp, new Template({inline: '<div>{{ctxProp}}</div>'}));
compiler.compile(MyComp).then((pv) => {
createView(pv);
@ -69,11 +80,11 @@ export function main() {
cd.detectChanges();
expect(DOM.getInnerHTML(view.nodes[0])).toEqual('Hello World!');
done();
async.done();
});
});
}));
it('should consume element binding changes', (done) => {
it('should consume element binding changes', inject([AsyncTestCompleter], (async) => {
tplResolver.setTemplate(MyComp, new Template({inline: '<div [id]="ctxProp"></div>'}));
compiler.compile(MyComp).then((pv) => {
@ -83,11 +94,11 @@ export function main() {
cd.detectChanges();
expect(view.nodes[0].id).toEqual('Hello World!');
done();
async.done();
});
});
}));
it('should consume binding to aria-* attributes', (done) => {
it('should consume binding to aria-* attributes', inject([AsyncTestCompleter], (async) => {
tplResolver.setTemplate(MyComp, new Template({inline: '<div [aria-label]="ctxProp"></div>'}));
compiler.compile(MyComp).then((pv) => {
@ -101,11 +112,11 @@ export function main() {
cd.detectChanges();
expect(DOM.getAttribute(view.nodes[0], 'aria-label')).toEqual('Changed aria label');
done();
async.done();
});
});
}));
it('should consume binding to property names where attr name and property name do not match', (done) => {
it('should consume binding to property names where attr name and property name do not match', inject([AsyncTestCompleter], (async) => {
tplResolver.setTemplate(MyComp, new Template({inline: '<div [tabindex]="ctxNumProp"></div>'}));
compiler.compile(MyComp).then((pv) => {
@ -118,11 +129,11 @@ export function main() {
cd.detectChanges();
expect(view.nodes[0].tabIndex).toEqual(5);
done();
async.done();
});
});
}));
it('should consume binding to inner-html', (done) => {
it('should consume binding to inner-html', inject([AsyncTestCompleter], (async) => {
tplResolver.setTemplate(MyComp, new Template({inline: '<div inner-html="{{ctxProp}}"></div>'}));
compiler.compile(MyComp).then((pv) => {
@ -136,11 +147,11 @@ export function main() {
cd.detectChanges();
expect(DOM.getInnerHTML(view.nodes[0])).toEqual('Some other <div>HTML</div>');
done();
async.done();
});
});
}));
it('should consume directive watch expression change.', (done) => {
it('should consume directive watch expression change.', inject([AsyncTestCompleter], (async) => {
var tpl =
'<div>' +
'<div my-dir [elprop]="ctxProp"></div>' +
@ -160,11 +171,11 @@ export function main() {
expect(view.elementInjectors[1].get(MyDir).dirProp).toEqual('Hi there!');
expect(view.elementInjectors[2].get(MyDir).dirProp).toEqual('Hi there!');
expect(view.elementInjectors[3].get(MyDir).dirProp).toEqual('One more Hello World!');
done();
async.done();
});
});
}));
it("should support pipes in bindings and bind config", (done) => {
it("should support pipes in bindings and bind config", inject([AsyncTestCompleter], (async) => {
tplResolver.setTemplate(MyComp,
new Template({
inline: '<component-with-pipes #comp [prop]="ctxProp | double"></component-with-pipes>',
@ -187,11 +198,11 @@ export function main() {
// it is doubled twice: once in the binding, second time in the bind config
expect(comp.prop).toEqual('aaaa');
done();
async.done();
});
});
}));
it('should support nested components.', (done) => {
it('should support nested components.', inject([AsyncTestCompleter], (async) => {
tplResolver.setTemplate(MyComp, new Template({
inline: '<child-cmp></child-cmp>',
directives: [ChildComp]
@ -203,12 +214,12 @@ export function main() {
cd.detectChanges();
expect(view.nodes[0].shadowRoot.childNodes[0].nodeValue).toEqual('hello');
done();
async.done();
});
});
}));
// GH issue 328 - https://github.com/angular/angular/issues/328
it('should support different directive types on a single node', (done) => {
it('should support different directive types on a single node', inject([AsyncTestCompleter], (async) => {
tplResolver.setTemplate(MyComp,
new Template({
inline: '<child-cmp my-dir [elprop]="ctxProp"></child-cmp>',
@ -225,11 +236,11 @@ export function main() {
expect(elInj.get(MyDir).dirProp).toEqual('Hello World!');
expect(elInj.get(ChildComp).dirProp).toEqual(null);
done();
async.done();
});
});
}));
it('should support directives where a binding attribute is not given', function(done) {
it('should support directives where a binding attribute is not given', inject([AsyncTestCompleter], (async) => {
tplResolver.setTemplate(MyComp,
new Template({
// No attribute "el-prop" specified.
@ -239,11 +250,11 @@ export function main() {
compiler.compile(MyComp).then((pv) => {
createView(pv);
done();
async.done();
});
});
}));
it('should support directives where a selector matches property binding', function(done) {
it('should support directives where a selector matches property binding', inject([AsyncTestCompleter], (async) => {
tplResolver.setTemplate(MyComp,
new Template({
inline: '<p [id]="ctxProp"></p>',
@ -263,11 +274,11 @@ export function main() {
expect(view.nodes[0].id).toEqual('other_id');
expect(DOM.getInnerHTML(view.nodes[0].shadowRoot.childNodes[0])).toEqual('Matched on id with other_id');
done();
async.done();
});
});
}));
it('should support template directives via `<template>` elements.', (done) => {
it('should support template directives via `<template>` elements.', inject([AsyncTestCompleter], (async) => {
tplResolver.setTemplate(MyComp,
new Template({
inline: '<div><template some-viewport var-greeting="some-tmpl"><copy-me>{{greeting}}</copy-me></template></div>',
@ -284,11 +295,11 @@ export function main() {
expect(childNodesOfWrapper.length).toBe(3);
expect(childNodesOfWrapper[1].childNodes[0].nodeValue).toEqual('hello');
expect(childNodesOfWrapper[2].childNodes[0].nodeValue).toEqual('again');
done();
async.done();
});
});
}));
it('should support template directives via `template` attribute.', (done) => {
it('should support template directives via `template` attribute.', inject([AsyncTestCompleter], (async) => {
tplResolver.setTemplate(MyComp, new Template({
inline: '<div><copy-me template="some-viewport: var greeting=some-tmpl">{{greeting}}</copy-me></div>',
directives: [SomeViewport]
@ -304,11 +315,11 @@ export function main() {
expect(childNodesOfWrapper.length).toBe(3);
expect(childNodesOfWrapper[1].childNodes[0].nodeValue).toEqual('hello');
expect(childNodesOfWrapper[2].childNodes[0].nodeValue).toEqual('again');
done();
async.done();
});
});
}));
it('should assign the component instance to a var-', (done) => {
it('should assign the component instance to a var-', inject([AsyncTestCompleter], (async) => {
tplResolver.setTemplate(MyComp, new Template({
inline: '<p><child-cmp var-alice></child-cmp></p>',
directives: [ChildComp]
@ -320,11 +331,11 @@ export function main() {
expect(view.contextWithLocals).not.toBe(null);
expect(view.contextWithLocals.get('alice')).toBeAnInstanceOf(ChildComp);
done();
async.done();
})
});
}));
it('should assign two component instances each with a var-', (done) => {
it('should assign two component instances each with a var-', inject([AsyncTestCompleter], (async) => {
tplResolver.setTemplate(MyComp, new Template({
inline: '<p><child-cmp var-alice></child-cmp><child-cmp var-bob></p>',
directives: [ChildComp]
@ -338,11 +349,11 @@ export function main() {
expect(view.contextWithLocals.get('bob')).toBeAnInstanceOf(ChildComp);
expect(view.contextWithLocals.get('alice')).not.toBe(view.contextWithLocals.get('bob'));
done();
async.done();
})
});
}));
it('should assign the component instance to a var- with shorthand syntax', (done) => {
it('should assign the component instance to a var- with shorthand syntax', inject([AsyncTestCompleter], (async) => {
tplResolver.setTemplate(MyComp, new Template({
inline: '<child-cmp #alice></child-cmp>',
directives: [ChildComp]
@ -354,11 +365,11 @@ export function main() {
expect(view.contextWithLocals).not.toBe(null);
expect(view.contextWithLocals.get('alice')).toBeAnInstanceOf(ChildComp);
done();
async.done();
})
});
}));
it('should assign the element instance to a user-defined variable', (done) => {
it('should assign the element instance to a user-defined variable', inject([AsyncTestCompleter], (async) => {
tplResolver.setTemplate(MyComp,
new Template({inline: '<p><div var-alice><i>Hello</i></div></p>'}));
@ -370,11 +381,11 @@ export function main() {
expect(value).not.toBe(null);
expect(value.tagName.toLowerCase()).toEqual('div');
done();
async.done();
})
});
}));
it('should provide binding configuration config to the component', (done) => {
it('should provide binding configuration config to the component', inject([AsyncTestCompleter], (async) => {
tplResolver.setTemplate(MyComp, new Template({
inline: '<push-cmp #cmp></push-cmp>',
directives: [[[PushBasedComp]]]
@ -395,11 +406,11 @@ export function main() {
cd.detectChanges();
expect(cmp.numberOfChecks).toEqual(2);
done();
async.done();
})
});
}));
it('should create a component that injects a @Parent', (done) => {
it('should create a component that injects a @Parent', inject([AsyncTestCompleter], (async) => {
tplResolver.setTemplate(MyComp, new Template({
inline: '<some-directive><cmp-with-parent #child></cmp-with-parent></some-directive>',
directives: [SomeDirective, CompWithParent]
@ -411,11 +422,11 @@ export function main() {
var childComponent = view.contextWithLocals.get('child');
expect(childComponent.myParent).toBeAnInstanceOf(SomeDirective);
done();
async.done();
})
});
}));
it('should create a component that injects an @Ancestor', (done) => {
it('should create a component that injects an @Ancestor', inject([AsyncTestCompleter], (async) => {
tplResolver.setTemplate(MyComp, new Template({
inline: `
<some-directive>
@ -432,11 +443,11 @@ export function main() {
var childComponent = view.contextWithLocals.get('child');
expect(childComponent.myAncestor).toBeAnInstanceOf(SomeDirective);
done();
async.done();
})
});
}));
it('should create a component that injects an @Ancestor through viewport directive', (done) => {
it('should create a component that injects an @Ancestor through viewport directive', inject([AsyncTestCompleter], (async) => {
tplResolver.setTemplate(MyComp, new Template({
inline: `
<some-directive>
@ -455,11 +466,11 @@ export function main() {
var childComponent = subview.contextWithLocals.get('child');
expect(childComponent.myAncestor).toBeAnInstanceOf(SomeDirective);
done();
})
});
async.done();
});
}));
it('should support events', (done) => {
it('should support events', inject([AsyncTestCompleter], (async) => {
tplResolver.setTemplate(MyComp, new Template({
inline: '<div emitter listener></div>',
directives: [DecoratorEmitingEvent, DecoratorListeningEvent]
@ -480,9 +491,9 @@ export function main() {
expect(emitter.msg).toEqual('fired !');
expect(listener.msg).toEqual('fired !');
done();
async.done();
});
});
}));
});
@ -492,7 +503,7 @@ export function main() {
tplResolver.setTemplate(MyComp, new Template({inline: inlineTpl}));
PromiseWrapper.then(compiler.compile(MyComp),
(value) => {
done("Test failure: should not have come here as an exception was expected");
throw new BaseException("Test failure: should not have come here as an exception was expected");
},
(err) => {
expect(err.message).toEqual(errMessage);
@ -501,45 +512,45 @@ export function main() {
);
}
it('should raise an error if no directive is registered for an unsupported DOM property', (done) => {
it('should raise an error if no directive is registered for an unsupported DOM property', inject([AsyncTestCompleter], (async) => {
expectCompileError(
'<div [some-prop]="foo"></div>',
'Missing directive to handle \'some-prop\' in MyComp: <div [some-prop]="foo">',
done
() => async.done()
);
});
}));
it('should raise an error if no directive is registered for a template with template bindings', (done) => {
it('should raise an error if no directive is registered for a template with template bindings', inject([AsyncTestCompleter], (async) => {
expectCompileError(
'<div><div template="if: foo"></div></div>',
'Missing directive to handle \'if\' in <div template="if: foo">',
done
() => async.done()
);
});
}));
it('should raise an error for missing template directive (1)', (done) => {
it('should raise an error for missing template directive (1)', inject([AsyncTestCompleter], (async) => {
expectCompileError(
'<div><template foo></template></div>',
'Missing directive to handle: <template foo>',
done
() => async.done()
);
});
}));
it('should raise an error for missing template directive (2)', (done) => {
it('should raise an error for missing template directive (2)', inject([AsyncTestCompleter], (async) => {
expectCompileError(
'<div><template *if="condition"></template></div>',
'Missing directive to handle: <template *if="condition">',
done
() => async.done()
);
});
}));
it('should raise an error for missing template directive (3)', (done) => {
it('should raise an error for missing template directive (3)', inject([AsyncTestCompleter], (async) => {
expectCompileError(
'<div *if="condition"></div>',
'Missing directive to handle \'if\' in MyComp: <div *if="condition">',
done
() => async.done()
);
});
}));
}
});
}

View File

@ -1,4 +1,16 @@
import {describe, xit, it, expect, beforeEach, ddescribe, iit, el, IS_NODEJS} from 'angular2/test_lib';
import {
AsyncTestCompleter,
beforeEach,
ddescribe,
describe,
el,
expect,
iit,
inject,
IS_NODEJS,
it,
xit,
} from 'angular2/test_lib';
import {StringMapWrapper, List} from 'angular2/src/facade/collection';
import {Type} from 'angular2/src/facade/lang';
@ -80,7 +92,7 @@ export function main() {
});
}
it('should support multiple content tags', (done) => {
it('should support multiple content tags', inject([AsyncTestCompleter], (async) => {
var temp = '<multiple-content-tags>' +
'<div>B</div>' +
'<div>C</div>' +
@ -89,11 +101,11 @@ export function main() {
compile(temp, [MultipleContentTagsComponent], (view, lc) => {
expect(view.nodes).toHaveText('(A, BC)');
done();
async.done();
});
});
}));
it('should redistribute only direct children', (done) => {
it('should redistribute only direct children', inject([AsyncTestCompleter], (async) => {
var temp = '<multiple-content-tags>' +
'<div>B<div class="left">A</div></div>' +
'<div>C</div>' +
@ -101,11 +113,11 @@ export function main() {
compile(temp, [MultipleContentTagsComponent], (view, lc) => {
expect(view.nodes).toHaveText('(, BAC)');
done();
async.done();
});
});
}));
it("should redistribute direct child viewcontainers when the light dom changes", (done) => {
it("should redistribute direct child viewcontainers when the light dom changes", inject([AsyncTestCompleter], (async) => {
var temp = '<multiple-content-tags>' +
'<div><div template="manual" class="left">A</div></div>' +
'<div>B</div>' +
@ -126,11 +138,11 @@ export function main() {
expect(view.nodes).toHaveText('(, B)');
done();
async.done();
});
});
}));
it("should redistribute when the light dom changes", (done) => {
it("should redistribute when the light dom changes", inject([AsyncTestCompleter], (async) => {
var temp = '<multiple-content-tags>' +
'<div template="manual" class="left">A</div>' +
'<div>B</div>' +
@ -151,11 +163,11 @@ export function main() {
expect(view.nodes).toHaveText('(, B)');
done();
async.done();
});
});
}));
it("should support nested components", (done) => {
it("should support nested components", inject([AsyncTestCompleter], (async) => {
var temp = '<outer-with-indirect-nested>' +
'<div>A</div>' +
'<div>B</div>' +
@ -164,11 +176,11 @@ export function main() {
compile(temp, [OuterWithIndirectNestedComponent], (view, lc) => {
expect(view.nodes).toHaveText('OUTER(SIMPLE(AB))');
done();
async.done();
});
});
}));
it("should support nesting with content being direct child of a nested component", (done) => {
it("should support nesting with content being direct child of a nested component", inject([AsyncTestCompleter], (async) => {
var temp = '<outer>' +
'<div template="manual" class="left">A</div>' +
'<div>B</div>' +
@ -184,11 +196,11 @@ export function main() {
lc.tick();
expect(view.nodes).toHaveText('OUTER(INNER(INNERINNER(A,BC)))');
done();
async.done();
});
});
}));
it('should redistribute when the shadow dom changes', (done) => {
it('should redistribute when the shadow dom changes', inject([AsyncTestCompleter], (async) => {
var temp = '<conditional-content>' +
'<div class="left">A</div>' +
'<div>B</div>' +
@ -211,9 +223,9 @@ export function main() {
expect(view.nodes).toHaveText('(, ABC)');
done();
async.done();
});
});
}));
//Implement once NgElement support changing a class
//it("should redistribute when a class has been added or removed");

View File

@ -1,4 +1,15 @@
import {describe, beforeEach, it, expect, ddescribe, iit, SpyObject, el} from 'angular2/test_lib';
import {
AsyncTestCompleter,
beforeEach,
ddescribe,
describe,
el,
expect,
iit,
inject,
it,
SpyObject,
} from 'angular2/test_lib';
import {
NativeShadowDomStrategy,
@ -114,7 +125,7 @@ export function main() {
expect(styleElement).toHaveText(".foo[_ngcontent-0] {\n\n}\n\n[_nghost-0] {\n\n}");
});
it('should inline @import rules', (done) => {
it('should inline @import rules', inject([AsyncTestCompleter], (async) => {
xhr.reply('http://base/one.css', '.one {}');
var template = el('<div><style>@import "one.css";</style></div>');
@ -133,9 +144,9 @@ export function main() {
expect(styleElement).toHaveText('');
parentpv.stylePromises[0].then((_) => {
expect(styleElement).toHaveText('.one[_ngcontent-0] {\n\n}');
done();
async.done();
});
});
}));
it('should return the same style given the same component', () => {
var template = el('<div><style>.foo {} :host {}</style></div>');

View File

@ -1,4 +1,15 @@
import {describe, it, expect, beforeEach, ddescribe, iit, xit, el} from 'angular2/test_lib';
import {
AsyncTestCompleter,
beforeEach,
ddescribe,
describe,
el,
expect,
iit,
inject,
it,
xit,
} from 'angular2/test_lib';
import {StyleInliner} from 'angular2/src/core/compiler/style_inliner';
import {isBlank} from 'angular2/src/facade/lang';
@ -28,7 +39,7 @@ export function main() {
expect(loadedCss).toEqual(css);
});
it('should inline @import rules', (done) => {
it('should inline @import rules', inject([AsyncTestCompleter], (async) => {
xhr.reply('http://base/one.css', '.one {}');
var css = '@import url("one.css");.main {}';
var loadedCss = inliner.inlineImports(css, 'http://base');
@ -37,16 +48,15 @@ export function main() {
loadedCss,
function(css) {
expect(css).toEqual('.one {}\n.main {}');
done();
async.done();
},
function(e) {
throw 'fail;'
}
);
});
}));
// TODO(vicb): fix the StyleInliner
it('should support url([unquoted url]) in @import rules', (done) => {
it('should support url([unquoted url]) in @import rules', inject([AsyncTestCompleter], (async) => {
xhr.reply('http://base/one.css', '.one {}');
var css = '@import url(one.css);.main {}';
var loadedCss = inliner.inlineImports(css, 'http://base');
@ -55,15 +65,15 @@ export function main() {
loadedCss,
function(css) {
expect(css).toEqual('.one {}\n.main {}');
done();
async.done();
},
function(e) {
throw 'fail;'
}
);
});
}));
it('should handle @import error gracefuly', (done) => {
it('should handle @import error gracefuly', inject([AsyncTestCompleter], (async) => {
var css = '@import "one.css";.main {}';
var loadedCss = inliner.inlineImports(css, 'http://base');
expect(loadedCss).toBePromise();
@ -71,15 +81,15 @@ export function main() {
loadedCss,
function(css) {
expect(css).toEqual('/* failed to import http://base/one.css */\n.main {}');
done();
async.done();
},
function(e) {
throw 'fail;'
}
);
});
}));
it('should inline multiple @import rules', (done) => {
it('should inline multiple @import rules', inject([AsyncTestCompleter], (async) => {
xhr.reply('http://base/one.css', '.one {}');
xhr.reply('http://base/two.css', '.two {}');
var css = '@import "one.css";@import "two.css";.main {}';
@ -89,15 +99,15 @@ export function main() {
loadedCss,
function(css) {
expect(css).toEqual('.one {}\n.two {}\n.main {}');
done();
async.done();
},
function(e) {
throw 'fail;'
}
);
});
}));
it('should inline nested @import rules', (done) => {
it('should inline nested @import rules', inject([AsyncTestCompleter], (async) => {
xhr.reply('http://base/one.css', '@import "two.css";.one {}');
xhr.reply('http://base/two.css', '.two {}');
var css = '@import "one.css";.main {}';
@ -107,15 +117,15 @@ export function main() {
loadedCss,
function(css) {
expect(css).toEqual('.two {}\n.one {}\n.main {}');
done();
async.done();
},
function(e) {
throw 'fail;'
}
);
});
}));
it('should handle circular dependencies gracefuly', (done) => {
it('should handle circular dependencies gracefuly', inject([AsyncTestCompleter], (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 {}';
@ -125,15 +135,15 @@ export function main() {
loadedCss,
function(css) {
expect(css).toEqual('.two {}\n.one {}\n.main {}');
done();
async.done();
},
function(e) {
throw 'fail;'
}
);
});
}));
it('should handle invalid @import fracefuly', (done) => {
it('should handle invalid @import fracefuly', inject([AsyncTestCompleter], (async) => {
// Invalid rule: the url is not quoted
var css = '@import one.css;.main {}';
var loadedCss = inliner.inlineImports(css, 'http://base/');
@ -142,17 +152,17 @@ export function main() {
loadedCss,
function(css) {
expect(css).toEqual('/* Invalid import rule: "@import one.css;" */.main {}');
done();
async.done();
},
function(e) {
throw 'fail;'
}
);
});
}));
});
describe('media query', () => {
it('should wrap inlined content in media query', (done) => {
it('should wrap inlined content in media query', inject([AsyncTestCompleter], (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/');
@ -161,17 +171,17 @@ export function main() {
loadedCss,
function(css) {
expect(css).toEqual('@media (min-width: 700px) and (orientation: landscape) {\n.one {}\n}\n');
done();
async.done();
},
function(e) {
throw 'fail;'
}
);
});
}));
});
describe('url rewritting', () => {
it('should rewrite url in inlined content', (done) => {
it('should rewrite url in inlined content', inject([AsyncTestCompleter], (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");}');
@ -185,13 +195,13 @@ export function main() {
".two {background-image: url('http://base/img/two.jpg');}\n" +
".one {background-image: url('http://base/one.jpg');}\n"
);
done();
async.done();
},
function(e) {
throw 'fail;'
}
);
});
}));
});
});
}

View File

@ -1,4 +1,15 @@
import {describe, it, expect, beforeEach, ddescribe, iit, xit, el} from 'angular2/test_lib';
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/core/compiler/template_loader';
import {UrlResolver} from 'angular2/src/core/compiler/url_resolver';
@ -21,18 +32,18 @@ export function main() {
expect(DOM.content(loader.load(template))).toHaveText('inline template');
});
it('should load templates through XHR', (done) => {
it('should load templates through XHR', inject([AsyncTestCompleter], (async) => {
xhr.expect('base/foo', 'xhr template');
var template = new Template({url: '/foo'});
loader.setBaseUrl(template, 'base');
loader.load(template).then((el) => {
expect(DOM.content(el)).toHaveText('xhr template');
done();
async.done();
});
xhr.flush();
});
}));
it('should cache template loaded through XHR', (done) => {
it('should cache template loaded through XHR', inject([AsyncTestCompleter], (async) => {
var firstEl;
xhr.expect('base/foo', 'xhr template');
var template = new Template({url: '/foo'});
@ -45,10 +56,10 @@ export function main() {
.then((el) =>{
expect(el).toBe(firstEl);
expect(DOM.content(el)).toHaveText('xhr template');
done();
async.done();
});
xhr.flush();
});
}));
it('should throw when no template is defined', () => {
var template = new Template({inline: null, url: null});
@ -56,7 +67,7 @@ export function main() {
.toThrowError('Templates should have either their url or inline property set');
});
it('should return a rejected Promise when xhr loading fails', (done) => {
it('should return a rejected Promise when xhr loading fails', inject([AsyncTestCompleter], (async) => {
xhr.expect('base/foo', null);
var template = new Template({url: '/foo'});
loader.setBaseUrl(template, 'base');
@ -64,11 +75,11 @@ export function main() {
function(_) { throw 'Unexpected response'; },
function(error) {
expect(error).toEqual('Failed to load base/foo');
done();
async.done();
}
)
xhr.flush();
});
}));
});
}