diff --git a/modules/angular2/src/testing/async.dart b/modules/angular2/src/testing/async.dart new file mode 100644 index 0000000000..44dd3363b7 --- /dev/null +++ b/modules/angular2/src/testing/async.dart @@ -0,0 +1,4 @@ +// This symbol is not used on the Dart side. This exists just as a stub. +async(Function fn) { + throw 'async() test wrapper not available for Dart.'; +} diff --git a/modules/angular2/src/testing/async.ts b/modules/angular2/src/testing/async.ts new file mode 100644 index 0000000000..dc401a708e --- /dev/null +++ b/modules/angular2/src/testing/async.ts @@ -0,0 +1,25 @@ +/** + * Wraps a test function in an asynchronous test zone. The test will automatically + * complete when all asynchronous calls within this zone are done. Can be used + * to wrap an {@link inject} call. + * + * Example: + * + * ``` + * it('...', async(inject([AClass], (object) => { + * object.doSomething.then(() => { + * expect(...); + * }) + * }); + * ``` + */ +export function async(fn: Function): Function { + return () => { + return new Promise((finishCallback, failCallback) => { + var AsyncTestZoneSpec = Zone['AsyncTestZoneSpec']; + var testZoneSpec = new AsyncTestZoneSpec(finishCallback, failCallback, 'test'); + var testZone = Zone.current.fork(testZoneSpec); + return testZone.run(fn); + }); + } +} diff --git a/modules/angular2/src/testing/async_test_completer.ts b/modules/angular2/src/testing/async_test_completer.ts new file mode 100644 index 0000000000..64688d27d1 --- /dev/null +++ b/modules/angular2/src/testing/async_test_completer.ts @@ -0,0 +1,13 @@ +import {PromiseCompleter} from 'angular2/src/facade/promise'; + +/** + * Injectable completer that allows signaling completion of an asynchronous test. Used internally. + */ +export class AsyncTestCompleter { + private _completer = new PromiseCompleter(); + done(value?: any) { this._completer.resolve(value); } + + fail(error?: any, stackTrace?: string) { this._completer.reject(error, stackTrace); } + + get promise(): Promise { return this._completer.promise; } +} diff --git a/modules/angular2/src/testing/fake_async.dart b/modules/angular2/src/testing/fake_async.dart index 4dcf294c59..81078154a2 100644 --- a/modules/angular2/src/testing/fake_async.dart +++ b/modules/angular2/src/testing/fake_async.dart @@ -4,8 +4,6 @@ import 'dart:async' show runZoned, ZoneSpecification; import 'package:quiver/testing/async.dart' as quiver; import 'package:angular2/src/facade/exceptions.dart' show BaseException; -import 'test_injector.dart' show getTestInjector, FunctionWithParamTokens; - const _u = const Object(); quiver.FakeAsync _fakeAsync = null; @@ -22,24 +20,11 @@ quiver.FakeAsync _fakeAsync = null; * * Returns a `Function` that wraps [fn]. */ -Function fakeAsync(dynamic /* Function | FunctionWithParamTokens */ fn) { +Function fakeAsync(Function fn) { if (_fakeAsync != null) { throw 'fakeAsync() calls can not be nested'; } - Function innerFn = null; - if (fn is FunctionWithParamTokens) { - if (fn.isAsync) { - throw 'Cannot wrap async test with fakeAsync'; - } - innerFn = () { getTestInjector().execute(fn); }; - } else if (fn is Function) { - innerFn = fn; - } else { - throw 'fakeAsync can wrap only test functions but got object of type ' + - fn.runtimeType.toString(); - } - return ([a0 = _u, a1 = _u, a2 = _u, @@ -58,7 +43,7 @@ Function fakeAsync(dynamic /* Function | FunctionWithParamTokens */ fn) { List args = [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9] .takeWhile((a) => a != _u) .toList(); - var res = Function.apply(innerFn, args); + var res = Function.apply(fn, args); _fakeAsync.flushMicrotasks(); if (async.periodicTimerCount > 0) { diff --git a/modules/angular2/src/testing/fake_async.ts b/modules/angular2/src/testing/fake_async.ts index 1073a2e878..d405ff0050 100644 --- a/modules/angular2/src/testing/fake_async.ts +++ b/modules/angular2/src/testing/fake_async.ts @@ -1,5 +1,5 @@ import {BaseException} from 'angular2/src/facade/exceptions'; -import {getTestInjector, FunctionWithParamTokens} from './test_injector'; +import {getTestInjector} from './test_injector'; let _FakeAsyncTestZoneSpecType = Zone['FakeAsyncTestZoneSpec']; @@ -19,7 +19,7 @@ let _FakeAsyncTestZoneSpecType = Zone['FakeAsyncTestZoneSpec']; * @param fn * @returns {Function} The function wrapped to be executed in the fakeAsync zone */ -export function fakeAsync(fn: Function | FunctionWithParamTokens): Function { +export function fakeAsync(fn: Function): Function { if (Zone.current.get('FakeAsyncTestZoneSpec') != null) { throw new BaseException('fakeAsync() calls can not be nested'); } @@ -27,20 +27,9 @@ export function fakeAsync(fn: Function | FunctionWithParamTokens): Function { let fakeAsyncTestZoneSpec = new _FakeAsyncTestZoneSpecType(); let fakeAsyncZone = Zone.current.fork(fakeAsyncTestZoneSpec); - let innerTestFn: Function = null; - - if (fn instanceof FunctionWithParamTokens) { - if (fn.isAsync) { - throw new BaseException('Cannot wrap async test with fakeAsync'); - } - innerTestFn = () => { getTestInjector().execute(fn as FunctionWithParamTokens); }; - } else { - innerTestFn = fn; - } - return function(...args) { let res = fakeAsyncZone.run(() => { - let res = innerTestFn(...args); + let res = fn(...args); flushMicrotasks(); return res; }); diff --git a/modules/angular2/src/testing/test_injector.ts b/modules/angular2/src/testing/test_injector.ts index ae8cc75784..dfa0723401 100644 --- a/modules/angular2/src/testing/test_injector.ts +++ b/modules/angular2/src/testing/test_injector.ts @@ -3,6 +3,11 @@ import {BaseException, ExceptionHandler} from 'angular2/src/facade/exceptions'; import {ListWrapper} from 'angular2/src/facade/collection'; import {FunctionWrapper, isPresent, Type} from 'angular2/src/facade/lang'; +import {async} from './async'; +import {AsyncTestCompleter} from './async_test_completer'; + +export {async} from './async'; + export class TestInjector { private _instantiated: boolean = false; @@ -35,15 +40,19 @@ export class TestInjector { return this._injector; } - execute(fn: FunctionWithParamTokens): any { - var additionalProviders = fn.additionalProviders(); - if (additionalProviders.length > 0) { - this.addProviders(additionalProviders); - } + get(token: any) { if (!this._instantiated) { this.createInjector(); } - return fn.execute(this._injector); + return this._injector.get(token); + } + + execute(tokens: any[], fn: Function): any { + if (!this._instantiated) { + this.createInjector(); + } + var params = tokens.map(t => this._injector.get(t)); + return FunctionWrapper.apply(fn, params); } } @@ -117,22 +126,47 @@ export function resetBaseTestProviders() { * * @param {Array} tokens * @param {Function} fn - * @return {FunctionWithParamTokens} + * @return {Function} */ -export function inject(tokens: any[], fn: Function): FunctionWithParamTokens { - return new FunctionWithParamTokens(tokens, fn, false); +export function inject(tokens: any[], fn: Function): Function { + let testInjector = getTestInjector(); + if (tokens.indexOf(AsyncTestCompleter) >= 0) { + // Return an async test method that returns a Promise if AsyncTestCompleter is one of the + // injected tokens. + return () => { + let completer: AsyncTestCompleter = testInjector.get(AsyncTestCompleter); + testInjector.execute(tokens, fn); + return completer.promise; + } + } else { + // Return a synchronous test method with the injected tokens. + return () => { return getTestInjector().execute(tokens, fn); }; + } } export class InjectSetupWrapper { constructor(private _providers: () => any) {} - inject(tokens: any[], fn: Function): FunctionWithParamTokens { - return new FunctionWithParamTokens(tokens, fn, false, this._providers); + private _addProviders() { + var additionalProviders = this._providers(); + if (additionalProviders.length > 0) { + getTestInjector().addProviders(additionalProviders); + } + } + + inject(tokens: any[], fn: Function): Function { + return () => { + this._addProviders(); + return inject(tokens, fn)(); + } } /** @Deprecated {use async(withProviders().inject())} */ - injectAsync(tokens: any[], fn: Function): FunctionWithParamTokens { - return new FunctionWithParamTokens(tokens, fn, true, this._providers); + injectAsync(tokens: any[], fn: Function): Function { + return () => { + this._addProviders(); + return injectAsync(tokens, fn)(); + } } } @@ -158,53 +192,8 @@ export function withProviders(providers: () => any) { * * @param {Array} tokens * @param {Function} fn - * @return {FunctionWithParamTokens} + * @return {Function} */ -export function injectAsync(tokens: any[], fn: Function): FunctionWithParamTokens { - return new FunctionWithParamTokens(tokens, fn, true); -} - -/** - * Wraps a test function in an asynchronous test zone. The test will automatically - * complete when all asynchronous calls within this zone are done. Can be used - * to wrap an {@link inject} call. - * - * Example: - * - * ``` - * it('...', async(inject([AClass], (object) => { - * object.doSomething.then(() => { - * expect(...); - * }) - * }); - * ``` - */ -export function async(fn: Function | FunctionWithParamTokens): FunctionWithParamTokens { - if (fn instanceof FunctionWithParamTokens) { - fn.isAsync = true; - return fn; - } else if (fn instanceof Function) { - return new FunctionWithParamTokens([], fn, true); - } else { - throw new BaseException('argument to async must be a function or inject()'); - } -} - -function emptyArray(): Array { - return []; -} - -export class FunctionWithParamTokens { - constructor(private _tokens: any[], public fn: Function, public isAsync: boolean, - public additionalProviders: () => any = emptyArray) {} - - /** - * Returns the value of the executed function. - */ - execute(injector: ReflectiveInjector): any { - var params = this._tokens.map(t => injector.get(t)); - return FunctionWrapper.apply(this.fn, params); - } - - hasToken(token: any): boolean { return this._tokens.indexOf(token) > -1; } +export function injectAsync(tokens: any[], fn: Function): Function { + return async(inject(tokens, fn)); } diff --git a/modules/angular2/src/testing/testing.ts b/modules/angular2/src/testing/testing.ts index 0d71843276..fb3ead6d9f 100644 --- a/modules/angular2/src/testing/testing.ts +++ b/modules/angular2/src/testing/testing.ts @@ -2,18 +2,9 @@ * Public Test Library for unit testing Angular2 Applications. Uses the * Jasmine framework. */ -import {global} from 'angular2/src/facade/lang'; -import {ListWrapper} from 'angular2/src/facade/collection'; -import {bind} from 'angular2/core'; +import {global, isPromise} from 'angular2/src/facade/lang'; -import { - FunctionWithParamTokens, - inject, - async, - injectAsync, - TestInjector, - getTestInjector -} from './test_injector'; +import {inject, async, injectAsync, TestInjector, getTestInjector} from './test_injector'; export {inject, async, injectAsync} from './test_injector'; @@ -73,22 +64,6 @@ export var fdescribe: Function = _global.fdescribe; */ export var xdescribe: Function = _global.xdescribe; -/** - * Signature for a synchronous test function (no arguments). - */ -export type SyncTestFn = () => void; - -/** - * Signature for an asynchronous test function which takes a - * `done` callback. - */ -export type AsyncTestFn = (done: () => void) => void; - -/** - * Signature for any simple testing function. - */ -export type AnyTestFn = SyncTestFn | AsyncTestFn | Function; - var jsmBeforeEach = _global.beforeEach; var jsmIt = _global.it; var jsmIIt = _global.fit; @@ -123,35 +98,27 @@ export function beforeEachProviders(fn): void { }); } -function runInAsyncTestZone(fnToExecute, finishCallback: Function, failCallback: Function, - testName = ''): any { - var AsyncTestZoneSpec = Zone['AsyncTestZoneSpec']; - var testZoneSpec = new AsyncTestZoneSpec(finishCallback, failCallback, testName); - var testZone = Zone.current.fork(testZoneSpec); - return testZone.run(fnToExecute); -} - -function _isPromiseLike(input): boolean { - return input && !!(input.then); -} - -function _it(jsmFn: Function, name: string, testFn: FunctionWithParamTokens | AnyTestFn, - testTimeOut: number): void { - var timeOut = testTimeOut; - if (testFn instanceof FunctionWithParamTokens) { - let testFnT = testFn; - jsmFn(name, (done) => { - if (testFnT.isAsync) { - runInAsyncTestZone(() => testInjector.execute(testFnT), done, done.fail, name); +function _wrapTestFn(fn: Function) { + // Wraps a test or beforeEach function to handle synchronous and asynchronous execution. + return (done: any) => { + if (fn.length === 0) { + let retVal = fn(); + if (isPromise(retVal)) { + // Asynchronous test function - wait for completion. + (>retVal).then(done, done.fail); } else { - testInjector.execute(testFnT); + // Synchronous test function - complete immediately. done(); } - }, timeOut); - } else { - // The test case doesn't use inject(). ie `it('test', (done) => { ... }));` - jsmFn(name, testFn, timeOut); - } + } else { + // Asynchronous test function that takes "done" as parameter. + fn(done); + } + }; +} + +function _it(jsmFn: Function, name: string, testFn: Function, testTimeOut: number): void { + jsmFn(name, _wrapTestFn(testFn), testTimeOut); } /** @@ -165,27 +132,8 @@ function _it(jsmFn: Function, name: string, testFn: FunctionWithParamTokens | An * * {@example testing/ts/testing.ts region='beforeEach'} */ -export function beforeEach(fn: FunctionWithParamTokens | AnyTestFn): void { - if (fn instanceof FunctionWithParamTokens) { - // The test case uses inject(). ie `beforeEach(inject([ClassA], (a) => { ... - // }));` - let fnT = fn; - jsmBeforeEach((done) => { - if (fnT.isAsync) { - runInAsyncTestZone(() => testInjector.execute(fnT), done, done.fail, 'beforeEach'); - } else { - testInjector.execute(fnT); - done(); - } - }); - } else { - // The test case doesn't use inject(). ie `beforeEach((done) => { ... }));` - if ((fn).length === 0) { - jsmBeforeEach(() => { (fn)(); }); - } else { - jsmBeforeEach((done) => { (fn)(done); }); - } - } +export function beforeEach(fn: Function): void { + jsmBeforeEach(_wrapTestFn(fn)); } /** @@ -200,8 +148,7 @@ export function beforeEach(fn: FunctionWithParamTokens | AnyTestFn): void { * * {@example testing/ts/testing.ts region='describeIt'} */ -export function it(name: string, fn: FunctionWithParamTokens | AnyTestFn, - timeOut: number = null): void { +export function it(name: string, fn: Function, timeOut: number = null): void { return _it(jsmIt, name, fn, timeOut); } @@ -216,16 +163,14 @@ export function it(name: string, fn: FunctionWithParamTokens | AnyTestFn, * * {@example testing/ts/testing.ts region='xit'} */ -export function xit(name: string, fn: FunctionWithParamTokens | AnyTestFn, - timeOut: number = null): void { +export function xit(name: string, fn: Function, timeOut: number = null): void { return _it(jsmXIt, name, fn, timeOut); } /** * See {@link fit}. */ -export function iit(name: string, fn: FunctionWithParamTokens | AnyTestFn, - timeOut: number = null): void { +export function iit(name: string, fn: Function, timeOut: number = null): void { return _it(jsmIIt, name, fn, timeOut); } @@ -239,7 +184,6 @@ export function iit(name: string, fn: FunctionWithParamTokens | AnyTestFn, * * {@example testing/ts/testing.ts region='fit'} */ -export function fit(name: string, fn: FunctionWithParamTokens | AnyTestFn, - timeOut: number = null): void { +export function fit(name: string, fn: Function, timeOut: number = null): void { return _it(jsmIIt, name, fn, timeOut); } diff --git a/modules/angular2/src/testing/testing_internal.ts b/modules/angular2/src/testing/testing_internal.ts index 7f7de03575..d706a36c34 100644 --- a/modules/angular2/src/testing/testing_internal.ts +++ b/modules/angular2/src/testing/testing_internal.ts @@ -1,12 +1,13 @@ import {StringMapWrapper} from 'angular2/src/facade/collection'; -import {global, isFunction, Math} from 'angular2/src/facade/lang'; +import {global, isPromise, Math} from 'angular2/src/facade/lang'; import {provide} from 'angular2/core'; -import {getTestInjector, FunctionWithParamTokens, inject} from './test_injector'; +import {AsyncTestCompleter} from './async_test_completer'; +import {getTestInjector, inject} from './test_injector'; import {browserDetection} from './utils'; -import {NgZone} from 'angular2/src/core/zone/ng_zone'; +export {AsyncTestCompleter} from './async_test_completer'; export {inject} from './test_injector'; export {expect, NgMatchers} from './matchers'; @@ -17,19 +18,6 @@ var _global = (typeof window === 'undefined' ? global : window); export var afterEach: Function = _global.afterEach; -export type SyncTestFn = () => void; -type AsyncTestFn = (done: () => void) => void; -type AnyTestFn = SyncTestFn | AsyncTestFn; - -/** - * Injectable completer that allows signaling completion of an asynchronous test. Used internally. - */ -export class AsyncTestCompleter { - constructor(private _done: Function) {} - - done(): void { this._done(); } -} - var jsmBeforeEach = _global.beforeEach; var jsmDescribe = _global.describe; var jsmDDescribe = _global.fdescribe; @@ -51,18 +39,15 @@ var testInjector = getTestInjector(); * Note: Jasmine own `beforeEach` is used by this library to handle DI providers. */ class BeforeEachRunner { - private _fns: Array = []; + private _fns: Array = []; constructor(private _parent: BeforeEachRunner) {} - beforeEach(fn: FunctionWithParamTokens | SyncTestFn): void { this._fns.push(fn); } + beforeEach(fn: Function): void { this._fns.push(fn); } run(): void { if (this._parent) this._parent.run(); - this._fns.forEach((fn) => { - return isFunction(fn) ? (fn)() : - (testInjector.execute(fn)); - }); + this._fns.forEach((fn) => { fn(); }); } } @@ -90,13 +75,13 @@ export function xdescribe(...args): void { return _describe(jsmXDescribe, ...args); } -export function beforeEach(fn: FunctionWithParamTokens | SyncTestFn): void { +export function beforeEach(fn: Function): void { if (runnerStack.length > 0) { // Inside a describe block, beforeEach() uses a BeforeEachRunner runnerStack[runnerStack.length - 1].beforeEach(fn); } else { // Top level beforeEach() are delegated to jasmine - jsmBeforeEach(fn); + jsmBeforeEach(fn); } } @@ -127,55 +112,37 @@ export function beforeEachBindings(fn): void { beforeEachProviders(fn); } -function _it(jsmFn: Function, name: string, testFn: FunctionWithParamTokens | AnyTestFn, - testTimeOut: number): void { +function _it(jsmFn: Function, name: string, testFn: Function, testTimeOut: number): void { var runner = runnerStack[runnerStack.length - 1]; var timeOut = Math.max(globalTimeOut, testTimeOut); - if (testFn instanceof FunctionWithParamTokens) { - // The test case uses inject(). ie `it('test', inject([AsyncTestCompleter], (async) => { ... - // }));` - let testFnT = testFn; + jsmFn(name, (done) => { + var completerProvider = provide(AsyncTestCompleter, { + useFactory: () => { + // Mark the test as async when an AsyncTestCompleter is injected in an it() + if (!inIt) throw new Error('AsyncTestCompleter can only be injected in an "it()"'); + return new AsyncTestCompleter(); + } + }); + testInjector.addProviders([completerProvider]); + runner.run(); - if (testFn.hasToken(AsyncTestCompleter)) { - jsmFn(name, (done) => { - var completerProvider = provide(AsyncTestCompleter, { - useFactory: () => { - // Mark the test as async when an AsyncTestCompleter is injected in an it() - if (!inIt) throw new Error('AsyncTestCompleter can only be injected in an "it()"'); - return new AsyncTestCompleter(done); - } - }); - - testInjector.addProviders([completerProvider]); - runner.run(); - - inIt = true; - testInjector.execute(testFnT); - inIt = false; - }, timeOut); + inIt = true; + if (testFn.length == 0) { + let retVal = testFn(); + if (isPromise(retVal)) { + // Asynchronous test function that returns a Promise - wait for completion. + (>retVal).then(done, done.fail); + } else { + // Synchronous test function - complete immediately. + done(); + } } else { - jsmFn(name, () => { - runner.run(); - testInjector.execute(testFnT); - }, timeOut); + // Asynchronous test function that takes in 'done' parameter. + testFn(done); } - - } else { - // The test case doesn't use inject(). ie `it('test', (done) => { ... }));` - - if ((testFn).length === 0) { - jsmFn(name, () => { - runner.run(); - (testFn)(); - }, timeOut); - } else { - jsmFn(name, (done) => { - runner.run(); - (testFn)(done); - }, timeOut); - } - } + inIt = false; + }, timeOut); } export function it(name, fn, timeOut = null): void { @@ -190,7 +157,6 @@ export function iit(name, fn, timeOut = null): void { return _it(jsmIIt, name, fn, timeOut); } - export interface GuinessCompatibleSpy extends jasmine.Spy { /** By chaining the spy with and.returnValue, all calls to the function will return a specific * value. */ diff --git a/modules/angular2/src/testing/testing_internal_core.dart b/modules/angular2/src/testing/testing_internal_core.dart index ecb1c008a0..6f23f4493e 100644 --- a/modules/angular2/src/testing/testing_internal_core.dart +++ b/modules/angular2/src/testing/testing_internal_core.dart @@ -26,31 +26,18 @@ import 'package:angular2/src/core/reflection/reflection_capabilities.dart'; import 'package:angular2/src/core/di/provider.dart' show bind; import 'package:angular2/src/facade/collection.dart' show StringMapWrapper; +import 'async_test_completer.dart'; +export 'async_test_completer.dart' show AsyncTestCompleter; + import 'test_injector.dart'; export 'test_injector.dart' show inject; TestInjector _testInjector = getTestInjector(); -bool _isCurrentTestAsync; -Future _currentTestFuture; bool _inIt = false; bool _initialized = false; List _platformProviders = []; List _applicationProviders = []; -class AsyncTestCompleter { - final _completer = new Completer(); - - AsyncTestCompleter() { - _currentTestFuture = this.future; - } - - void done() { - _completer.complete(); - } - - Future get future => _completer.future; -} - void setDartBaseTestProviders(List platform, List application) { _platformProviders = platform; _applicationProviders = application; @@ -70,18 +57,15 @@ void testSetup() { gns.beforeEach(() { _testInjector.reset(); - _currentTestFuture = null; }); var completerProvider = bind(AsyncTestCompleter).toFactory(() { // Mark the test as async when an AsyncTestCompleter is injected in an it(), if (!_inIt) throw 'AsyncTestCompleter can only be injected in an "it()"'; - _isCurrentTestAsync = true; return new AsyncTestCompleter(); }); gns.beforeEach(() { - _isCurrentTestAsync = false; _testInjector.addProviders([completerProvider]); }); } @@ -113,22 +97,16 @@ void beforeEachBindings(Function fn) { void beforeEach(fn) { testSetup(); - if (fn is! FunctionWithParamTokens) fn = - new FunctionWithParamTokens([], fn, false); - gns.beforeEach(() { - _testInjector.execute(fn); - }); + gns.beforeEach(fn); } void _it(gnsFn, name, fn) { testSetup(); - if (fn is! FunctionWithParamTokens) fn = - new FunctionWithParamTokens([], fn, false); gnsFn(name, () { _inIt = true; - _testInjector.execute(fn); + var retVal = fn(); _inIt = false; - if (_isCurrentTestAsync) return _currentTestFuture; + return retVal; }); } diff --git a/modules/angular2/test/testing/testing_public_spec.ts b/modules/angular2/test/testing/testing_public_spec.ts index c7848c7a35..15877a9f36 100644 --- a/modules/angular2/test/testing/testing_public_spec.ts +++ b/modules/angular2/test/testing/testing_public_spec.ts @@ -150,6 +150,19 @@ export function main() { expect(value).toEqual('async value'); }))); + it('should allow use of "done"', (done) => { + inject([FancyService], (service) => { + let count = 0; + let id = setInterval(() => { + count++; + if (count > 2) { + clearInterval(id); + done(); + } + }, 5); + })(); // inject needs to be invoked explicitly with (). + }); + describe('using beforeEach', () => { beforeEach(inject([FancyService], (service) => { service.value = 'value modified in beforeEach'; })); @@ -174,6 +187,15 @@ export function main() { withProviders(() => [bind(FancyService).toValue(new FancyService())]) .inject([FancyService], (service) => { expect(service.value).toEqual('real value'); })); + + it('should return value from inject', () => { + let retval = withProviders(() => [bind(FancyService).toValue(new FancyService())]) + .inject([FancyService], (service) => { + expect(service.value).toEqual('real value'); + return 10; + })(); + expect(retval).toBe(10); + }); }); }); diff --git a/modules_dart/angular2_testing/lib/angular2_testing.dart b/modules_dart/angular2_testing/lib/angular2_testing.dart index 07fa13aee9..f59974a855 100644 --- a/modules_dart/angular2_testing/lib/angular2_testing.dart +++ b/modules_dart/angular2_testing/lib/angular2_testing.dart @@ -79,8 +79,7 @@ dynamic _runInjectableFunction(Function fn) { tokens.add(token); } - var injectFn = new FunctionWithParamTokens(tokens, fn, false); - return _testInjector.execute(injectFn); + return _testInjector.execute(tokens, fn); } /// Use the test injector to get bindings and run a function.