diff --git a/lib/mock/zone.dart b/lib/mock/zone.dart index ce8e57d80..af23eab80 100644 --- a/lib/mock/zone.dart +++ b/lib/mock/zone.dart @@ -2,6 +2,16 @@ library angular.mock_zone; import 'dart:async' as dart_async; +// async and sync are function compositions. +class FunctionComposition { + Function outer; + Function inner; + + FunctionComposition(this.outer, this.inner); + + call() => outer(inner)(); +} + final _asyncQueue = []; final _timerQueue = <_TimerSpec>[]; final _asyncErrors = []; @@ -144,7 +154,9 @@ noMoreAsync() { * ... * })); */ -async(Function fn) => () { +async(Function fn) => new FunctionComposition(_asyncOuter, fn); + +_asyncOuter(Function fn) => () { _noMoreAsync = false; _asyncErrors.clear(); _timerQueue.clear(); @@ -191,7 +203,9 @@ _createTimer(Function fn, Duration duration, bool periodic) { * Enforces synchronous code. Any calls to scheduleMicrotask inside of 'sync' * will throw an exception. */ -sync(Function fn) => () { +sync(Function fn) => new FunctionComposition(_syncOuter, fn); + +_syncOuter(Function fn) => () { _asyncErrors.clear(); dart_async.runZoned(fn, zoneSpecification: new dart_async.ZoneSpecification( diff --git a/test/_specs.dart b/test/_specs.dart index a48aef112..c61289b0e 100644 --- a/test/_specs.dart +++ b/test/_specs.dart @@ -6,10 +6,9 @@ import 'package:angular/angular.dart'; import 'package:angular/mock/module.dart'; import 'package:collection/wrappers.dart' show DelegatingList; -import 'jasmine_syntax.dart'; +import 'jasmine_syntax.dart' as jasmine_syntax; export 'dart:html'; -export 'jasmine_syntax.dart' hide main; export 'package:unittest/unittest.dart'; export 'package:unittest/mock.dart'; export 'package:di/dynamic_injector.dart'; @@ -246,9 +245,24 @@ class JQuery extends DelegatingList { shadowRoot() => new JQuery((this[0] as Element).shadowRoot); } +// Jasmine syntax +_injectify(fn) => fn is FunctionComposition ? fn.outer(inject(fn.inner)) : inject(fn); +beforeEachModule(fn) => jasmine_syntax.beforeEach(module(fn), priority:1); + +beforeEach(fn) => jasmine_syntax.beforeEach(_injectify(fn)); +afterEach(fn) => jasmine_syntax.afterEach(_injectify(fn)); +it(name, fn) => jasmine_syntax.it(name, _injectify(fn)); +iit(name, fn) => jasmine_syntax.iit(name, _injectify(fn)); +xit(name, fn) => jasmine_syntax.xit(name, fn); +xdescribe(name, fn) => jasmine_syntax.xdescribe(name, fn); +ddescribe(name, fn) => jasmine_syntax.ddescribe(name, fn); +describe(name, fn) => jasmine_syntax.describe(name, fn); + +var jasmine = jasmine_syntax.jasmine; + main() { - beforeEach(setUpInjector); - beforeEach(() => wrapFn(sync)); - afterEach(tearDownInjector); + jasmine_syntax.wrapFn(sync); + jasmine_syntax.beforeEach(setUpInjector, priority:3); + jasmine_syntax.afterEach(tearDownInjector); } diff --git a/test/animate/animation_loop_spec.dart b/test/animate/animation_loop_spec.dart index 9a582fd86..191c90cb8 100644 --- a/test/animate/animation_loop_spec.dart +++ b/test/animate/animation_loop_spec.dart @@ -96,4 +96,4 @@ class MockAnimationFrame implements AnimationFrame { completer.complete(time); } } -} \ No newline at end of file +} diff --git a/test/core/core_directive_spec.dart b/test/core/core_directive_spec.dart index 7cfa9d032..658e34ecc 100644 --- a/test/core/core_directive_spec.dart +++ b/test/core/core_directive_spec.dart @@ -5,9 +5,9 @@ import '../_specs.dart'; void main() { describe('DirectiveMap', () { - beforeEach(module((Module module) { + beforeEachModule((Module module) { module..type(AnnotatedIoComponent); - })); + }); it('should extract attr map from annotated component', inject((DirectiveMap directives) { var annotations = directives.annotationsFor(AnnotatedIoComponent); diff --git a/test/core/parser/generated_getter_setter_spec.dart b/test/core/parser/generated_getter_setter_spec.dart index 0e601ce95..847ae8672 100644 --- a/test/core/parser/generated_getter_setter_spec.dart +++ b/test/core/parser/generated_getter_setter_spec.dart @@ -6,10 +6,10 @@ import 'generated_getter_setter.dart'; main() { describe('hybrid getter-setter', () { - beforeEach(module((Module module) { + beforeEachModule((Module module) { module.type(Parser, implementedBy: DynamicParser); module.type(ClosureMap, implementedBy: StaticClosureMap); - })); + }); parser_spec.main(); }); } diff --git a/test/core/parser/generated_parser_spec.dart b/test/core/parser/generated_parser_spec.dart index 298f247ed..d42648ea4 100644 --- a/test/core/parser/generated_parser_spec.dart +++ b/test/core/parser/generated_parser_spec.dart @@ -10,14 +10,14 @@ class AlwaysThrowError implements DynamicParser { main() { describe('generated parser', () { - beforeEach(module((Module module) { + beforeEachModule((Module module) { module.type(Parser, implementedBy: StaticParser); module.type(DynamicParser, implementedBy: AlwaysThrowError); module.factory(StaticParserFunctions, (Injector injector) { return generated_functions.functions(); }); - })); + }); parser_spec.main(); }); } diff --git a/test/core/parser/parser_spec.dart b/test/core/parser/parser_spec.dart index 6e1003a8a..4f3e9ca57 100644 --- a/test/core/parser/parser_spec.dart +++ b/test/core/parser/parser_spec.dart @@ -48,10 +48,10 @@ main() { Map context; Parser parser; FilterMap filters; - beforeEach(module((Module module) { + beforeEachModule((Module module) { module.type(IncrementFilter); module.type(SubstringFilter); - })); + }); beforeEach(inject((Parser injectedParser, FilterMap injectedFilters) { parser = injectedParser; filters = injectedFilters; diff --git a/test/core/parser/static_parser_spec.dart b/test/core/parser/static_parser_spec.dart index fa8ad0164..bf0953f3e 100644 --- a/test/core/parser/static_parser_spec.dart +++ b/test/core/parser/static_parser_spec.dart @@ -11,11 +11,11 @@ class AlwaysReturnX implements DynamicParser { main() { describe('static parser', () { - beforeEach(module((Module m) { + beforeEachModule((Module m) { m.type(Parser, implementedBy: StaticParser); m.type(DynamicParser, implementedBy: AlwaysReturnX); m.value(StaticParserFunctions, new StaticParserFunctions(EVAL, ASSIGN)); - })); + }); it('should run a static function', inject((Parser parser) { diff --git a/test/core/scope_spec.dart b/test/core/scope_spec.dart index 70bcffb2b..8e32bf204 100644 --- a/test/core/scope_spec.dart +++ b/test/core/scope_spec.dart @@ -8,7 +8,7 @@ import 'dart:math'; void main() { describe('scope', () { - beforeEach(module((Module module) { + beforeEachModule((Module module) { Map context = {}; module ..value(GetterCache, new GetterCache({})) @@ -22,7 +22,7 @@ void main() { ..type(_SortFilter) ..type(_IdentityFilter) ..type(_MapKeys); - })); + }); describe('AST Bridge', () { it('should watch field', inject((Logger logger, Map context, RootScope rootScope) { @@ -465,7 +465,7 @@ void main() { log.add(event.currentScope.context['id']); } - beforeEach(module(() { + beforeEachModule(() { return (RootScope rootScope) { log = []; child = rootScope.createChild({'id': 1}); @@ -479,7 +479,7 @@ void main() { grandChild.on('myEvent').listen(logger); greatGrandChild.on('myEvent').listen(logger); }; - })); + }); it(r'should bubble event up to the root scope', inject((RootScope rootScope) { grandChild.emit(r'myEvent'); @@ -487,11 +487,11 @@ void main() { })); - it(r'should dispatch exceptions to the exceptionHandler', () { - module((Module module) { + describe('exceptions', () { + beforeEachModule((Module module) { module.type(ExceptionHandler, implementedBy: LoggingExceptionHandler); }); - inject((ExceptionHandler e) { + it(r'should dispatch exceptions to the exceptionHandler', (ExceptionHandler e) { LoggingExceptionHandler exceptionHandler = e; child.on('myEvent').listen((e) { throw 'bubbleException'; }); grandChild.emit(r'myEvent'); @@ -500,7 +500,6 @@ void main() { }); }); - it(r'should allow stopping event propagation', inject((RootScope rootScope) { child.on('myEvent').listen((event) { event.stopPropagation(); }); grandChild.emit(r'myEvent'); @@ -799,10 +798,21 @@ void main() { expect(log).toEqual('1'); })); + describe(r'exceptions', () { + var log; + beforeEachModule((Module module) { + return module.type(ExceptionHandler, implementedBy: LoggingExceptionHandler); + }); - it(r'should catch exceptions', () { - module((Module module) => module.type(ExceptionHandler, implementedBy: LoggingExceptionHandler)); - inject((RootScope rootScope, ExceptionHandler e) { + beforeEach(inject((RootScope rootScope) { + rootScope.context['log'] = () { log += 'digest;'; return null; }; + log = ''; + rootScope.watch('log()', (v, o) => null); + rootScope.digest(); + log = ''; + })); + + it(r'should catch exceptions', (RootScope rootScope, ExceptionHandler e) { LoggingExceptionHandler exceptionHandler = e; var log = []; var child = rootScope.createChild({}); @@ -814,21 +824,6 @@ void main() { exceptionHandler.errors.removeAt(0); exceptionHandler.assertEmpty(); }); - }); - - - describe(r'exceptions', () { - var log; - beforeEach(module((Module module) { - return module.type(ExceptionHandler, implementedBy: LoggingExceptionHandler); - })); - beforeEach(inject((RootScope rootScope) { - rootScope.context['log'] = () { log += 'digest;'; return null; }; - log = ''; - rootScope.watch('log()', (v, o) => null); - rootScope.digest(); - log = ''; - })); it(r'should execute and return value and update', inject( @@ -882,10 +877,20 @@ void main() { expect(log).toEqual('1'); })); + describe(r'exceptions', () { + var log; + beforeEachModule((Module module) { + return module.type(ExceptionHandler, implementedBy: LoggingExceptionHandler); + }); + beforeEach(inject((RootScope rootScope) { + rootScope.context['log'] = () { log += 'digest;'; return null; }; + log = ''; + rootScope.watch('log()', (v, o) => null, readOnly: true); + rootScope.digest(); + log = ''; + })); - it(r'should catch exceptions', () { - module((Module module) => module.type(ExceptionHandler, implementedBy: LoggingExceptionHandler)); - inject((RootScope rootScope, ExceptionHandler e) { + it(r'should catch exceptions', (RootScope rootScope, ExceptionHandler e) { LoggingExceptionHandler exceptionHandler = e; var log = []; var child = rootScope.createChild({}); @@ -897,22 +902,6 @@ void main() { exceptionHandler.errors.removeAt(0); exceptionHandler.assertEmpty(); }); - }); - - - describe(r'exceptions', () { - var log; - beforeEach(module((Module module) { - return module.type(ExceptionHandler, implementedBy: LoggingExceptionHandler); - })); - beforeEach(inject((RootScope rootScope) { - rootScope.context['log'] = () { log += 'digest;'; return null; }; - log = ''; - rootScope.watch('log()', (v, o) => null, readOnly: true); - rootScope.digest(); - log = ''; - })); - it(r'should execute and return value and update', inject( (RootScope rootScope, ExceptionHandler e) { @@ -1037,11 +1026,11 @@ void main() { })); - it(r'should delegate exceptions', () { - module((Module module) { + describe('exceptions', () { + beforeEachModule((Module module) { module.type(ExceptionHandler, implementedBy: LoggingExceptionHandler); }); - inject((RootScope rootScope, ExceptionHandler e) { + it(r'should delegate exceptions', (RootScope rootScope, ExceptionHandler e) { LoggingExceptionHandler exceptionHandler = e; rootScope.watch('a', (n, o) {throw 'abc';}); rootScope.context['a'] = 1; @@ -1052,6 +1041,7 @@ void main() { }); + it(r'should fire watches in order of addition', inject((RootScope rootScope) { // this is not an external guarantee, just our own sanity var log = ''; @@ -1407,65 +1397,60 @@ void main() { describe('domRead/domWrite', () { - it(r'should run writes before reads', () { - module((Module module) { - module.type(ExceptionHandler, implementedBy: LoggingExceptionHandler); + beforeEachModule((Module module) { + module.type(ExceptionHandler, implementedBy: LoggingExceptionHandler); + }); + + it(r'should run writes before reads', (RootScope rootScope, Logger logger, ExceptionHandler e) { + LoggingExceptionHandler exceptionHandler = e as LoggingExceptionHandler; + rootScope.domWrite(() { + logger('write1'); + rootScope.domWrite(() => logger('write2')); + throw 'write1'; }); - inject((RootScope rootScope, Logger logger, ExceptionHandler e) { - LoggingExceptionHandler exceptionHandler = e as LoggingExceptionHandler; - rootScope.domWrite(() { - logger('write1'); - rootScope.domWrite(() => logger('write2')); - throw 'write1'; - }); - rootScope.domRead(() { - logger('read1'); - rootScope.domRead(() => logger('read2')); - rootScope.domWrite(() => logger('write3')); - throw 'read1'; - }); - rootScope.watch('value', (_, __) => logger('observe'), readOnly: true); - rootScope.flush(); - expect(logger).toEqual(['write1', 'write2', 'observe', 'read1', 'read2', 'write3']); - expect(exceptionHandler.errors.length).toEqual(2); - expect(exceptionHandler.errors[0].error).toEqual('write1'); - expect(exceptionHandler.errors[1].error).toEqual('read1'); + rootScope.domRead(() { + logger('read1'); + rootScope.domRead(() => logger('read2')); + rootScope.domWrite(() => logger('write3')); + throw 'read1'; }); + rootScope.watch('value', (_, __) => logger('observe'), readOnly: true); + rootScope.flush(); + expect(logger).toEqual(['write1', 'write2', 'observe', 'read1', 'read2', 'write3']); + expect(exceptionHandler.errors.length).toEqual(2); + expect(exceptionHandler.errors[0].error).toEqual('write1'); + expect(exceptionHandler.errors[1].error).toEqual('read1'); }); }); describe('exceptionHander', () { - it('should call ExceptionHandler on zone errors', () { - module((Module module) { - module.type(ExceptionHandler, implementedBy: LoggingExceptionHandler); - }); - async((inject((RootScope rootScope, NgZone zone, ExceptionHandler e) { - zone.run(() { - scheduleMicrotask(() => throw 'my error'); - }); - var errors = (e as LoggingExceptionHandler).errors; - expect(errors.length).toEqual(1); - expect(errors.first.error).toEqual('my error'); - }))); + beforeEachModule((Module module) { + module.type(ExceptionHandler, implementedBy: LoggingExceptionHandler); }); - it('should call ExceptionHandler on digest errors', () { - module((Module module) { - module.type(ExceptionHandler, implementedBy: LoggingExceptionHandler); + it('should call ExceptionHandler on zone errors', + async((RootScope rootScope, NgZone zone, ExceptionHandler e) { + zone.run(() { + scheduleMicrotask(() => throw 'my error'); }); - async((inject((RootScope rootScope, NgZone zone, ExceptionHandler e) { - rootScope.context['badOne'] = () => new Map(); - rootScope.watch('badOne()', (_, __) => null); - - try { - zone.run(() => null); - } catch(_) {} - - var errors = (e as LoggingExceptionHandler).errors; - expect(errors.length).toEqual(1); - expect(errors.first.error, startsWith('Model did not stabilize')); - }))); - }); + var errors = (e as LoggingExceptionHandler).errors; + expect(errors.length).toEqual(1); + expect(errors.first.error).toEqual('my error'); + })); + + it('should call ExceptionHandler on digest errors', + async((RootScope rootScope, NgZone zone, ExceptionHandler e) { + rootScope.context['badOne'] = () => new Map(); + rootScope.watch('badOne()', (_, __) => null); + + try { + zone.run(() => null); + } catch(_) {} + + var errors = (e as LoggingExceptionHandler).errors; + expect(errors.length).toEqual(1); + expect(errors.first.error, startsWith('Model did not stabilize')); + })); }); }); } diff --git a/test/core/templateurl_spec.dart b/test/core/templateurl_spec.dart index ee6887535..6b5db113e 100644 --- a/test/core/templateurl_spec.dart +++ b/test/core/templateurl_spec.dart @@ -46,11 +46,11 @@ void main() { })); describe('loading with http rewriting', () { - beforeEach(module((Module module) { + beforeEachModule((Module module) { module ..type(HtmlAndCssComponent) ..type(UrlRewriter, implementedBy: PrefixedUrlRewriter); - })); + }); it('should use the UrlRewriter for both HTML and CSS URLs', async(inject( (Http $http, Compiler $compile, Scope $rootScope, Logger log, @@ -78,14 +78,14 @@ void main() { describe('async template loading', () { - beforeEach(module((Module module) { + beforeEachModule((Module module) { module ..type(LogAttrDirective) ..type(SimpleUrlComponent) ..type(HtmlAndCssComponent) ..type(OnlyCssComponent) ..type(InlineWithCssComponent); - })); + }); it('should replace element with template from url', async(inject( (Http $http, Compiler $compile, Scope $rootScope, Logger log, @@ -204,11 +204,11 @@ void main() { }); describe('multiple css loading', () { - beforeEach(module((Module module) { + beforeEachModule((Module module) { module ..type(LogAttrDirective) ..type(HtmlAndMultipleCssComponent); - })); + }); it('should load multiple CSS files into a style', async(inject( (Http $http, Compiler $compile, Scope $rootScope, Logger log, diff --git a/test/core/zone_spec.dart b/test/core/zone_spec.dart index 9cd04be41..5c6332f71 100644 --- a/test/core/zone_spec.dart +++ b/test/core/zone_spec.dart @@ -8,10 +8,10 @@ void main() { describe('zone', () { var zone; var exceptionHandler; - beforeEach(module((Module module) { + beforeEachModule((Module module) { exceptionHandler = new LoggingExceptionHandler(); module.value(ExceptionHandler, exceptionHandler); - })); + }); beforeEach(inject((Logger log, ExceptionHandler eh) { zone = new NgZone(); diff --git a/test/core_dom/compiler_spec.dart b/test/core_dom/compiler_spec.dart index 948b29772..a77a68fa8 100644 --- a/test/core_dom/compiler_spec.dart +++ b/test/core_dom/compiler_spec.dart @@ -5,18 +5,18 @@ import '../_specs.dart'; forBothCompilers(fn) { describe('walking compiler', () { - beforeEach(module((Module m) { + beforeEachModule((Module m) { m.type(Compiler, implementedBy: WalkingCompiler); return m; - })); + }); fn(); }); describe('tagging compiler', () { - beforeEach(module((Module m) { + beforeEachModule((Module m) { m.type(Compiler, implementedBy: TaggingCompiler); return m; - })); + }); fn(); }); } @@ -25,10 +25,8 @@ void main() { forBothCompilers(() => describe('dte.compiler', () { TestBed _; - HttpBackend httpBackend; - beforeEach(module((Module module) { - httpBackend = new MockHttpBackend(); + beforeEachModule((Module module) { module ..type(TabComponent) @@ -58,10 +56,8 @@ void main() { ..type(SimpleAttachComponent) ..type(SimpleComponent) ..type(ExprAttrComponent) - ..type(SayHelloFilter) - ..value(HttpBackend, httpBackend) - ..value(MockHttpBackend, httpBackend); - })); + ..type(SayHelloFilter); + }); beforeEach(inject((TestBed tb) => _ = tb)); @@ -437,6 +433,14 @@ void main() { }))); describe('lifecycle', () { + beforeEachModule((Module module) { + var httpBackend = new MockHttpBackend(); + + module + ..value(HttpBackend, httpBackend) + ..value(MockHttpBackend, httpBackend); + }); + it('should fire onTemplate method', async(inject((Compiler $compile, Logger logger, MockHttpBackend backend) { backend.whenGET('some/template.url').respond('
WORKED
'); var scope = _.rootScope.createChild({}); diff --git a/test/core_dom/cookies_spec.dart b/test/core_dom/cookies_spec.dart index f5e5a4458..3ad9684f3 100644 --- a/test/core_dom/cookies_spec.dart +++ b/test/core_dom/cookies_spec.dart @@ -31,9 +31,9 @@ void main() { describe('browser cookies', () { var cookies; - beforeEach(module((Module module) { + beforeEachModule((Module module) { module.type(ExceptionHandler, implementedBy: LoggingExceptionHandler); - })); + }); beforeEach(inject((BrowserCookies iCookies) { iCookies.cookiePath = '/'; diff --git a/test/core_dom/element_binder_spec.dart b/test/core_dom/element_binder_spec.dart index 43cd43c16..117252a99 100644 --- a/test/core_dom/element_binder_spec.dart +++ b/test/core_dom/element_binder_spec.dart @@ -22,13 +22,13 @@ main() => describe('ElementBinder', () { var directives; var node = null; - beforeEach(module((Module module) { + beforeEachModule((Module module) { module ..type(_DirectiveAttr) ..type(_Component) ..type(_IgnoreChildren) ..type(_Structural); - })); + }); beforeEach(inject((DirectiveMap d, ElementBinderFactory f) { directives = d; diff --git a/test/core_dom/http_spec.dart b/test/core_dom/http_spec.dart index b44d651d7..4dd829ec2 100644 --- a/test/core_dom/http_spec.dart +++ b/test/core_dom/http_spec.dart @@ -41,7 +41,7 @@ void main() { microLeap(); } - beforeEach(module((Module module) { + beforeEachModule((Module module) { backend = new MockHttpBackend(); locationWrapper = new MockLocationWrapper(); cache = new FakeCache(); @@ -49,7 +49,7 @@ void main() { ..value(HttpBackend, backend) ..value(LocationWrapper, locationWrapper) ..type(ExceptionHandler, implementedBy: LoggingExceptionHandler); - })); + }); afterEach(inject((ExceptionHandler eh, Scope scope) { scope.apply(); @@ -906,9 +906,9 @@ void main() { }); describe('url rewriting', () { - beforeEach(module((Module module) { + beforeEachModule((Module module) { module.type(UrlRewriter, implementedBy: SubstringRewriter); - })); + }); it('should rewrite URLs before calling the backend', async(inject((Http http, NgZone zone) { diff --git a/test/core_dom/ng_mustache_spec.dart b/test/core_dom/ng_mustache_spec.dart index 135871178..9bc9ef348 100644 --- a/test/core_dom/ng_mustache_spec.dart +++ b/test/core_dom/ng_mustache_spec.dart @@ -5,9 +5,9 @@ import '../_specs.dart'; main() { describe('ng-mustache', () { TestBed _; - beforeEach(module((Module module) { + beforeEachModule((Module module) { module.type(_HelloFilter); - })); + }); beforeEach(inject((TestBed tb) => _ = tb)); it('should replace {{}} in text', inject((Compiler $compile, Scope rootScope, Injector injector, DirectiveMap directives) { diff --git a/test/core_dom/selector_spec.dart b/test/core_dom/selector_spec.dart index ebb345979..579bf7aa1 100644 --- a/test/core_dom/selector_spec.dart +++ b/test/core_dom/selector_spec.dart @@ -42,7 +42,7 @@ main() { var directives; beforeEach(() => log = []); - beforeEach(module((Module module) { + beforeEachModule((Module module) { module ..type(_BElement) ..type(_BClass) @@ -61,7 +61,7 @@ main() { ..type(_TwoDirectives) ..type(_OneOfTwoDirectives) ..type(_TwoOfTwoDirectives); - })); + }); beforeEach(inject((DirectiveMap directives) { selector = (node) => directives.selector.match(node); })); diff --git a/test/core_dom/shadow_root_options_spec.dart b/test/core_dom/shadow_root_options_spec.dart index 9cfa40261..72a2f40ba 100644 --- a/test/core_dom/shadow_root_options_spec.dart +++ b/test/core_dom/shadow_root_options_spec.dart @@ -45,7 +45,7 @@ main() { Injector injector; Scope $rootScope; - beforeEach(module((Module module) { + beforeEachModule((Module module) { module ..type(ApplyAuthorStyleComponent) ..type(ResetStyleInheritanceComponent) @@ -56,7 +56,7 @@ main() { $rootScope = injector.get(Scope); directives = injector.get(DirectiveMap); }; - })); + }); it('should respect the apply-author-style option', async(inject(() { var element = $( diff --git a/test/directive/ng_bind_html_spec.dart b/test/directive/ng_bind_html_spec.dart index 791bc7df0..d6bcfa851 100644 --- a/test/directive/ng_bind_html_spec.dart +++ b/test/directive/ng_bind_html_spec.dart @@ -16,16 +16,17 @@ main() { expect(element.html()).toEqual('Google!'); })); - it('should use injected NodeValidator and override default sanitize behavior', - module((Module module) { - module.factory(dom.NodeValidator, (_) { - final validator = new NodeValidatorBuilder(); - validator.allowNavigation(new AnyUriPolicy()); - validator.allowTextElements(); - return validator; + describe('injected NodeValidator', () { + beforeEachModule((Module module) { + module.factory(dom.NodeValidator, (_) { + final validator = new NodeValidatorBuilder(); + validator.allowNavigation(new AnyUriPolicy()); + validator.allowTextElements(); + return validator; + }); }); - inject((Scope scope, Injector injector, Compiler compiler, DirectiveMap directives) { + it('should use injected NodeValidator and override default sanitize behavior', (Scope scope, Injector injector, Compiler compiler, DirectiveMap directives) { var element = $('
'); compiler(element, directives)(injector, element); scope.context['htmlVar'] = 'Google!'; @@ -33,7 +34,7 @@ main() { // Sanitation allows href attributes per injected sanitizer. expect(element.html()).toEqual('Google!'); }); - })); + }); }); } diff --git a/test/directive/ng_form_spec.dart b/test/directive/ng_form_spec.dart index 6780ecf3b..fa51cc02e 100644 --- a/test/directive/ng_form_spec.dart +++ b/test/directive/ng_form_spec.dart @@ -552,14 +552,15 @@ void main() { expect(form.classes.contains('ng-required-invalid')).toBe(false); })); - it('should display the valid and invalid CSS classes on the element for custom validations', () { - module((Module module) { + describe('custom validators', () { + beforeEachModule((Module module) { module.type(MyCustomFormValidator); }); - inject((TestBed _, Scope scope) { + + it('should display the valid and invalid CSS classes on the element for custom validations', (TestBed _, Scope scope) { var form = _.compile('
' + - ' ' + - '
'); + ' ' + + ''); scope.apply(); @@ -567,7 +568,7 @@ void main() { expect(form.classes.contains('custom-valid')).toBe(false); scope.apply(() { - scope.context['myModel'] = 'yes'; + scope.context['myModel'] = 'yes'; }); expect(form.classes.contains('custom-valid')).toBe(true); @@ -694,16 +695,14 @@ void main() { })); describe('regression tests: form', () { - it('should be resolvable by injector if configured by user.', () { - module((Module module) { - module.type(NgForm); - }); + beforeEachModule((Module module) { + module.type(NgForm); + }); - inject((Injector injector, Compiler compiler, DirectiveMap directives) { - var element = $('
'); - compiler(element, directives)(injector, element); - // The only expectation is that this doesn't throw - }); + it('should be resolvable by injector if configured by user.', (Injector injector, Compiler compiler, DirectiveMap directives) { + var element = $('
'); + compiler(element, directives)(injector, element); + // The only expectation is that this doesn't throw }); }); }); diff --git a/test/directive/ng_if_spec.dart b/test/directive/ng_if_spec.dart index e9072ecc4..4a37aceae 100644 --- a/test/directive/ng_if_spec.dart +++ b/test/directive/ng_if_spec.dart @@ -17,12 +17,10 @@ class ChildController { main() { var compile, html, element, rootScope, logger, directives; - void configInjector() { - module((Module module) { - module - ..type(ChildController) - ..type(LogAttrDirective); - }); + void configInjector(Module module) { + module + ..type(ChildController) + ..type(LogAttrDirective); } void configState() { @@ -42,7 +40,7 @@ main() { htmlForElements.forEach((html) { var directiveName = html.contains('ng-if') ? 'ng-if' : 'ng-unless'; describe(directiveName, () { - beforeEach(configInjector); + beforeEachModule(configInjector); beforeEach(configState); (exclusive ? iit : it)(should, () { callback(html); diff --git a/test/directive/ng_model_spec.dart b/test/directive/ng_model_spec.dart index 750d4ee9e..5b0d2d219 100644 --- a/test/directive/ng_model_spec.dart +++ b/test/directive/ng_model_spec.dart @@ -7,10 +7,11 @@ void main() { describe('ng-model', () { TestBed _; - beforeEach(module((Module module) { - module.type(ControllerWithNoLove); - module.type(MyCustomInputValidator); - })); + beforeEachModule((Module module) { + module + ..type(ControllerWithNoLove) + ..type(MyCustomInputValidator); + }); beforeEach(inject((TestBed tb) => _ = tb)); diff --git a/test/jasmine_syntax.dart b/test/jasmine_syntax.dart index 13def2068..d4f06aabb 100644 --- a/test/jasmine_syntax.dart +++ b/test/jasmine_syntax.dart @@ -13,18 +13,28 @@ _maybeWrapFn(fn) => () { } }; -it(name, fn) => unit.test(name, _maybeWrapFn(fn)); -iit(name, fn) => unit.solo_test(name, _maybeWrapFn(fn)); +var _beforeEachFnsForCurrentTest = []; +_withSetup(fn) => () { + _beforeEachFnsForCurrentTest.sort((a, b) => Comparable.compare(b[1], a[1])); + _beforeEachFnsForCurrentTest.forEach((fn) => fn[0]()); + try { + fn(); + } finally { + _beforeEachFnsForCurrentTest = []; + } +}; + +it(name, fn) => unit.test(name, _withSetup(_maybeWrapFn(fn))); +iit(name, fn) => unit.solo_test(name, _withSetup(_maybeWrapFn(fn))); xit(name, fn) {} xdescribe(name, fn) {} ddescribe(name, fn) => describe(name, fn, true); - class Describe { Describe parent; String name; bool exclusive; - List beforeEachFns = []; + List beforeEachFns = []; List afterEachFns = []; Describe(this.name, this.parent, [bool this.exclusive=false]) { @@ -34,7 +44,7 @@ class Describe { } setUp() { - beforeEachFns.forEach((fn) => fn()); + _beforeEachFnsForCurrentTest.addAll(beforeEachFns); } tearDown() { @@ -56,6 +66,7 @@ describe(name, fn, [bool exclusive=false]) { unit.group(name, () { unit.setUp(currentDescribe.setUp); fn(); + unit.tearDown(currentDescribe.tearDown); }); } finally { @@ -63,7 +74,7 @@ describe(name, fn, [bool exclusive=false]) { } } -beforeEach(fn) => currentDescribe.beforeEachFns.add(fn); +beforeEach(fn, {priority: 0}) => currentDescribe.beforeEachFns.add([fn, priority]); afterEach(fn) => currentDescribe.afterEachFns.insert(0, fn); wrapFn(fn) => _wrapFn = fn; diff --git a/test/jasmines_syntax_spec.dart b/test/jasmines_syntax_spec.dart new file mode 100644 index 000000000..9fe6968fa --- /dev/null +++ b/test/jasmines_syntax_spec.dart @@ -0,0 +1,63 @@ +library jasmine_syntax_spec; + +import 'jasmine_syntax.dart'; +import 'package:unittest/unittest.dart' as unit; + +main() { + describe('jasmine syntax', () { + describe('beforeEach priority', () { + var log = []; + beforeEach(() { + log.add("first p0"); + }); + + beforeEach(() { + log.add("p0"); + }, priority: 0); + + beforeEach(() { + log.add("p1"); + }, priority: 1); + + it('should call beforeEach in the correct order', () { + unit.expect(log.join(';'), unit.equals('p1;first p0;p0')); + }); + }); + + describe('beforeEach priority with nested describes', () { + var log; + beforeEach(() { + log = []; + }, priority: 2); + + beforeEach(() { + log.add("p0Outer"); + }, priority: 0); + + beforeEach(() { + log.add("p1Outer"); + }, priority: 1); + + it('should call beforeEach in the correct order', () { + unit.expect(log.join(';'), unit.equals('p1Outer;p0Outer')); + }); + + describe('inner', () { + beforeEach(() { + log.add("p0Inner"); + }, priority: 0); + + beforeEach(() { + log.add("p1Inner"); + }, priority: 1); + + + it('should call beforeEach in the correct order', () { + unit.expect(log.join(';'), unit.equals('p1Outer;p1Inner;p0Outer;p0Inner')); + }); + }); + + + }); + }); +} diff --git a/test/mock/test_bed_spec.dart b/test/mock/test_bed_spec.dart index c2cbaf772..138d24848 100644 --- a/test/mock/test_bed_spec.dart +++ b/test/mock/test_bed_spec.dart @@ -9,10 +9,10 @@ void main() { Injector injector; Scope $rootScope; - beforeEach(module((Module module) { + beforeEachModule((Module module) { module..type(MyTestBedDirective); return (TestBed tb) => _ = tb; - })); + }); it('should allow for a scope-based compile', () { diff --git a/test/playback/playback_http_spec.dart b/test/playback/playback_http_spec.dart index 9c2fe4b1b..15f4a493e 100644 --- a/test/playback/playback_http_spec.dart +++ b/test/playback/playback_http_spec.dart @@ -6,11 +6,11 @@ import 'package:angular/playback/playback_http.dart'; void main() { describe('Playback HTTP', () { MockHttpBackend backend; - beforeEach(module((Module m) { + beforeEachModule((Module m) { backend = new MockHttpBackend(); var wrapper = new HttpBackendWrapper(backend); m..value(HttpBackendWrapper, wrapper)..type(PlaybackHttpBackendConfig); - })); + }); afterEach(() { backend.verifyNoOutstandingRequest(); @@ -18,9 +18,9 @@ void main() { }); describe('RecordingHttpBackend', () { - beforeEach(module((Module m) { + beforeEachModule((Module m) { m.type(HttpBackend, implementedBy: RecordingHttpBackend); - })); + }); it('should record a request', async(inject((Http http) { @@ -51,9 +51,9 @@ void main() { describe('PlaybackHttpBackend', () { - beforeEach(module((Module m) { + beforeEachModule((Module m) { m.type(HttpBackend, implementedBy: PlaybackHttpBackend); - })); + }); it('should replay a request', async(inject((Http http, HttpBackend hb) { (hb as PlaybackHttpBackend).data = { diff --git a/test/routing/ng_bind_route_spec.dart b/test/routing/ng_bind_route_spec.dart index e2ed604a6..7a348e234 100644 --- a/test/routing/ng_bind_route_spec.dart +++ b/test/routing/ng_bind_route_spec.dart @@ -9,9 +9,9 @@ main() { describe('ngBindRoute', () { TestBed _; - beforeEach(module((Module m) => m + beforeEachModule((Module m) => m ..install(new AngularMockModule()) - ..type(RouteInitializerFn, implementedBy: NestedRouteInitializer))); + ..type(RouteInitializerFn, implementedBy: NestedRouteInitializer)); beforeEach(inject((TestBed tb) { _ = tb; diff --git a/test/routing/ng_view_spec.dart b/test/routing/ng_view_spec.dart index 1ae83e9f5..d4b717724 100644 --- a/test/routing/ng_view_spec.dart +++ b/test/routing/ng_view_spec.dart @@ -10,11 +10,11 @@ main() { TestBed _; Router router; - beforeEach(module((Module m) { + beforeEachModule((Module m) { m ..install(new AngularMockModule()) ..type(RouteInitializerFn, implementedBy: FlatRouteInitializer); - })); + }); beforeEach(inject((TestBed tb, Router _router, TemplateCache templates) { _ = tb; @@ -80,11 +80,11 @@ main() { TestBed _; Router router; - beforeEach(module((Module m) { + beforeEachModule((Module m) { m ..install(new AngularMockModule()) ..type(RouteInitializerFn, implementedBy: NestedRouteInitializer); - })); + }); beforeEach(inject((TestBed tb, Router _router, TemplateCache templates) { _ = tb; diff --git a/test/routing/routing_spec.dart b/test/routing/routing_spec.dart index 9431f2a45..c7d8aeaf1 100644 --- a/test/routing/routing_spec.dart +++ b/test/routing/routing_spec.dart @@ -11,7 +11,7 @@ main() { TestBed _; Router router; - beforeEach(async(module((Module m) { + beforeEachModule((Module m) { _initRoutesCalls = 0; _router = null; router = new Router(useFragment: false, windowImpl: new MockWindow()); @@ -19,7 +19,7 @@ main() { ..install(new AngularMockModule()) ..factory(RouteInitializerFn, (_) => initRoutes) ..value(Router, router); - }))); + }); beforeEach(inject((TestBed tb) { _ = tb;