refactor(di): unified di injector and core injector
BREAKING CHANGES: * InjectAsync and InjectLazy have been removed * toAsyncFactory has been removed
This commit is contained in:
@@ -85,6 +85,7 @@ export function main() {
|
||||
inject([AsyncTestCompleter], (async) => {
|
||||
var refPromise =
|
||||
bootstrap(HelloRootDirectiveIsNotCmp, testBindings, (e, t) => { throw e; });
|
||||
|
||||
PromiseWrapper.then(refPromise, null, (reason) => {
|
||||
expect(reason.message)
|
||||
.toContain(
|
||||
@@ -108,24 +109,6 @@ export function main() {
|
||||
expect(refPromise).not.toBe(null);
|
||||
});
|
||||
|
||||
it('should resolve an injector promise and contain bindings',
|
||||
inject([AsyncTestCompleter], (async) => {
|
||||
var refPromise = bootstrap(HelloRootCmp, testBindings);
|
||||
refPromise.then((ref) => {
|
||||
expect(ref.injector.get(HelloRootCmp)).toBeAnInstanceOf(HelloRootCmp);
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should provide the application component in the injector',
|
||||
inject([AsyncTestCompleter], (async) => {
|
||||
var refPromise = bootstrap(HelloRootCmp, testBindings);
|
||||
refPromise.then((ref) => {
|
||||
expect(ref.injector.get(HelloRootCmp)).toBeAnInstanceOf(HelloRootCmp);
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should display hello world', inject([AsyncTestCompleter], (async) => {
|
||||
var refPromise = bootstrap(HelloRootCmp, testBindings);
|
||||
refPromise.then((ref) => {
|
||||
@@ -151,7 +134,7 @@ export function main() {
|
||||
bootstrap(HelloRootCmp3, [testBindings, bind("appBinding").toValue("BoundValue")]);
|
||||
|
||||
refPromise.then((ref) => {
|
||||
expect(ref.injector.get(HelloRootCmp3).appBinding).toEqual("BoundValue");
|
||||
expect(ref.hostComponent.appBinding).toEqual("BoundValue");
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
@@ -161,7 +144,7 @@ export function main() {
|
||||
var refPromise = bootstrap(HelloRootCmp4, testBindings);
|
||||
|
||||
refPromise.then((ref) => {
|
||||
expect(ref.injector.get(HelloRootCmp4).lc).toBe(ref.injector.get(LifeCycle));
|
||||
expect(ref.hostComponent.lc).toBe(ref.injector.get(LifeCycle));
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
@@ -183,7 +166,7 @@ export function main() {
|
||||
.then((refs: ApplicationRef[]) => {
|
||||
var registry = refs[0].injector.get(TestabilityRegistry);
|
||||
var testabilities =
|
||||
[refs[0].injector.asyncGet(Testability), refs[1].injector.asyncGet(Testability)];
|
||||
[refs[0].injector.get(Testability), refs[1].injector.get(Testability)];
|
||||
PromiseWrapper.all(testabilities)
|
||||
.then((testabilities: Testability[]) => {
|
||||
expect(registry.findTestabilityInTree(el)).toEqual(testabilities[0]);
|
||||
|
||||
@@ -34,17 +34,13 @@ import {
|
||||
} from 'angular2/src/core/compiler/element_injector';
|
||||
import * as dirAnn from 'angular2/src/core/annotations_impl/annotations';
|
||||
import {
|
||||
Parent,
|
||||
Ancestor,
|
||||
Unbounded,
|
||||
Attribute,
|
||||
Query,
|
||||
Component,
|
||||
Directive,
|
||||
onDestroy
|
||||
} from 'angular2/annotations';
|
||||
import * as ngDiAnn from 'angular2/src/core/annotations_impl/visibility';
|
||||
import {bind, Injector, Binding, resolveBindings, Optional, Inject, Injectable} from 'angular2/di';
|
||||
import {bind, Injector, Binding, resolveBindings, Optional, Inject, Injectable, Self, Parent, Ancestor, Unbounded, self} from 'angular2/di';
|
||||
import * as diAnn from 'angular2/src/di/annotations_impl';
|
||||
import {AppProtoView, AppView} from 'angular2/src/core/compiler/view';
|
||||
import {ViewContainerRef} from 'angular2/src/core/compiler/view_container_ref';
|
||||
@@ -78,13 +74,16 @@ class DummyElementRef extends SpyObject {
|
||||
noSuchMethod(m) { return super.noSuchMethod(m); }
|
||||
}
|
||||
|
||||
@Injectable(self)
|
||||
class SimpleDirective {}
|
||||
|
||||
class SimpleService {}
|
||||
|
||||
@Injectable(self)
|
||||
class SomeOtherDirective {}
|
||||
|
||||
var _constructionCount = 0;
|
||||
@Injectable(self)
|
||||
class CountingDirective {
|
||||
count;
|
||||
constructor() {
|
||||
@@ -93,6 +92,7 @@ class CountingDirective {
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable(self)
|
||||
class FancyCountingDirective extends CountingDirective {
|
||||
constructor() { super(); }
|
||||
}
|
||||
@@ -139,6 +139,12 @@ class NeedsService {
|
||||
constructor(@Inject("service") service) { this.service = service; }
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
class NeedsAncestorService {
|
||||
service: any;
|
||||
constructor(@Ancestor() @Inject("service") service) { this.service = service; }
|
||||
}
|
||||
|
||||
class HasEventEmitter {
|
||||
emitter;
|
||||
constructor() { this.emitter = "emitter"; }
|
||||
@@ -581,7 +587,6 @@ export function main() {
|
||||
expect(d.dependency).toBeAnInstanceOf(SimpleDirective);
|
||||
});
|
||||
|
||||
|
||||
it("should instantiate hostInjector injectables that have dependencies with set visibility",
|
||||
function() {
|
||||
var childInj = parentChildInjectors(
|
||||
@@ -597,7 +602,7 @@ export function main() {
|
||||
bind('injectable2')
|
||||
.toFactory(
|
||||
(val) => `${val}-injectable2`,
|
||||
[[new diAnn.Inject('injectable1'), new ngDiAnn.Parent()]])
|
||||
[[new diAnn.Inject('injectable1'), new diAnn.Parent()]])
|
||||
]
|
||||
}))]);
|
||||
expect(childInj.get('injectable2')).toEqual('injectable1-injectable2');
|
||||
@@ -648,7 +653,8 @@ export function main() {
|
||||
expect(shadowInj.get(NeedsService).service).toEqual('hostService');
|
||||
});
|
||||
|
||||
it("should not instantiate a directive in a view that depends on hostInjector bindings of a decorator directive", () => {
|
||||
it("should not instantiate a directive in a view that has an ancestor dependency on hostInjector"+
|
||||
" bindings of a decorator directive", () => {
|
||||
expect(() => {
|
||||
hostShadowInjectors(
|
||||
ListWrapper.concat([
|
||||
@@ -657,7 +663,7 @@ export function main() {
|
||||
hostInjector: [bind('service').toValue('hostService')]})
|
||||
)], extraBindings),
|
||||
|
||||
ListWrapper.concat([NeedsService], extraBindings)
|
||||
ListWrapper.concat([NeedsAncestorService], extraBindings)
|
||||
);
|
||||
}).toThrowError(new RegExp("No provider for service!"));
|
||||
});
|
||||
|
||||
@@ -55,7 +55,8 @@ main() {
|
||||
});
|
||||
|
||||
describe('Error handling', () {
|
||||
it('should preserve Error stack traces thrown from components', inject([
|
||||
//TODO: vsavkin reenable this test after merging DI and EI
|
||||
xit('should preserve Error stack traces thrown from components', inject([
|
||||
TestComponentBuilder,
|
||||
AsyncTestCompleter
|
||||
], (tb, async) {
|
||||
@@ -69,7 +70,8 @@ main() {
|
||||
});
|
||||
}));
|
||||
|
||||
it('should preserve non-Error stack traces thrown from components', inject([
|
||||
//TODO: vsavkin reenable this test after merging DI and EI
|
||||
xit('should preserve non-Error stack traces thrown from components', inject([
|
||||
TestComponentBuilder,
|
||||
AsyncTestCompleter
|
||||
], (tb, async) {
|
||||
|
||||
@@ -33,7 +33,18 @@ import {
|
||||
} from 'angular2/src/facade/lang';
|
||||
import {PromiseWrapper, EventEmitter, ObservableWrapper} from 'angular2/src/facade/async';
|
||||
|
||||
import {Injector, bind, Injectable, Binding, forwardRef, OpaqueToken, Inject} from 'angular2/di';
|
||||
import {
|
||||
Injector,
|
||||
bind,
|
||||
Injectable,
|
||||
Binding,
|
||||
forwardRef,
|
||||
OpaqueToken,
|
||||
Inject,
|
||||
Parent,
|
||||
Ancestor,
|
||||
Unbounded
|
||||
} from 'angular2/di';
|
||||
import {
|
||||
PipeFactory,
|
||||
PipeRegistry,
|
||||
@@ -45,18 +56,9 @@ import {
|
||||
ON_PUSH
|
||||
} from 'angular2/change_detection';
|
||||
|
||||
import {
|
||||
Directive,
|
||||
Component,
|
||||
View,
|
||||
Parent,
|
||||
Ancestor,
|
||||
Unbounded,
|
||||
Attribute,
|
||||
Query
|
||||
} from 'angular2/annotations';
|
||||
import {Directive, Component, View, Attribute, Query} from 'angular2/annotations';
|
||||
import * as viewAnn from 'angular2/src/core/annotations_impl/view';
|
||||
import * as visAnn from 'angular2/src/core/annotations_impl/visibility';
|
||||
import * as visAnn from 'angular2/src/di/annotations_impl';
|
||||
|
||||
import {QueryList} from 'angular2/src/core/compiler/query_list';
|
||||
|
||||
|
||||
@@ -156,7 +156,7 @@ export function main() {
|
||||
}
|
||||
|
||||
function directiveBinding({metadata}: {metadata?: any} = {}) {
|
||||
return new DirectiveBinding(Key.get("dummy"), null, [], false, [], [], [], metadata);
|
||||
return new DirectiveBinding(Key.get("dummy"), null, [], [], [], [], metadata);
|
||||
}
|
||||
|
||||
function createRenderProtoView(elementBinders = null, type: renderApi.ViewType = null) {
|
||||
|
||||
@@ -210,7 +210,7 @@ export function main() {
|
||||
});
|
||||
|
||||
it('should hydrate the view', () => {
|
||||
var injector = new Injector([], null, false);
|
||||
var injector = Injector.resolveAndCreate([]);
|
||||
manager.createRootHostView(wrapPv(hostProtoView), null, injector);
|
||||
expect(utils.spy('hydrateRootHostView')).toHaveBeenCalledWith(createdViews[0], injector);
|
||||
expect(renderer.spy('hydrateView')).toHaveBeenCalledWith(createdViews[0].render);
|
||||
@@ -301,7 +301,7 @@ export function main() {
|
||||
});
|
||||
|
||||
it('should hydrate the view', () => {
|
||||
var injector = new Injector([], null, false);
|
||||
var injector = Injector.resolveAndCreate([]);
|
||||
var contextView =
|
||||
createView(createProtoView([createEmptyElBinder(), createEmptyElBinder()]));
|
||||
manager.createViewInContainer(elementRef(parentView, 0), 0, wrapPv(childProtoView),
|
||||
|
||||
@@ -42,7 +42,7 @@ export function main() {
|
||||
var directiveResolver;
|
||||
var utils;
|
||||
|
||||
function createInjector() { return new Injector([], null, false); }
|
||||
function createInjector() { return Injector.resolveAndCreate([]); }
|
||||
|
||||
function createDirectiveBinding(type) {
|
||||
var annotation = directiveResolver.resolve(type);
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
import {
|
||||
AsyncTestCompleter,
|
||||
beforeEach,
|
||||
ddescribe,
|
||||
describe,
|
||||
expect,
|
||||
iit,
|
||||
inject,
|
||||
it,
|
||||
xit,
|
||||
} from 'angular2/test_lib';
|
||||
import {Injector, bind, Key} from 'angular2/di';
|
||||
import {Inject, InjectPromise, Injectable} from 'angular2/src/di/decorators';
|
||||
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
|
||||
import {stringify} from 'angular2/src/facade/lang';
|
||||
|
||||
class UserList {}
|
||||
|
||||
function fetchUsers() {
|
||||
return PromiseWrapper.resolve(new UserList());
|
||||
}
|
||||
|
||||
class SynchronousUserList {}
|
||||
|
||||
@Injectable()
|
||||
class UserController {
|
||||
list: UserList;
|
||||
constructor(list: UserList) { this.list = list; }
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
class AsyncUserController {
|
||||
userList;
|
||||
constructor(@InjectPromise(UserList) userList) { this.userList = userList; }
|
||||
}
|
||||
|
||||
export function main() {
|
||||
describe("async injection", function() {
|
||||
|
||||
describe("asyncGet", function() {
|
||||
it('should return a promise', function() {
|
||||
var injector = Injector.resolveAndCreate([bind(UserList).toAsyncFactory(fetchUsers)]);
|
||||
var p = injector.asyncGet(UserList);
|
||||
expect(p).toBePromise();
|
||||
});
|
||||
|
||||
it('should return a promise when the binding is sync', function() {
|
||||
var injector = Injector.resolveAndCreate([SynchronousUserList]);
|
||||
var p = injector.asyncGet(SynchronousUserList);
|
||||
expect(p).toBePromise();
|
||||
});
|
||||
|
||||
it("should return a promise when the binding is sync (from cache)", function() {
|
||||
var injector = Injector.resolveAndCreate([UserList]);
|
||||
expect(injector.get(UserList)).toBeAnInstanceOf(UserList);
|
||||
expect(injector.asyncGet(UserList)).toBePromise();
|
||||
});
|
||||
|
||||
it('should return the injector', inject([AsyncTestCompleter], (async) => {
|
||||
var injector = Injector.resolveAndCreate([]);
|
||||
var p = injector.asyncGet(Injector);
|
||||
p.then(function(injector) {
|
||||
expect(injector).toBe(injector);
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should return a promise when instantiating a sync binding ' +
|
||||
'with an async dependency',
|
||||
inject([AsyncTestCompleter], (async) => {
|
||||
var injector = Injector.resolveAndCreate(
|
||||
[bind(UserList).toAsyncFactory(fetchUsers), UserController]);
|
||||
|
||||
injector.asyncGet(UserController)
|
||||
.then(function(userController) {
|
||||
expect(userController).toBeAnInstanceOf(UserController);
|
||||
expect(userController.list).toBeAnInstanceOf(UserList);
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it("should create only one instance (async + async)",
|
||||
inject([AsyncTestCompleter], (async) => {
|
||||
var injector = Injector.resolveAndCreate([bind(UserList).toAsyncFactory(fetchUsers)]);
|
||||
|
||||
var ul1 = injector.asyncGet(UserList);
|
||||
var ul2 = injector.asyncGet(UserList);
|
||||
|
||||
PromiseWrapper.all([ul1, ul2])
|
||||
.then(function(uls) {
|
||||
expect(uls[0]).toBe(uls[1]);
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it("should create only one instance (sync + async)", inject([AsyncTestCompleter], (async) => {
|
||||
var injector = Injector.resolveAndCreate([UserList]);
|
||||
|
||||
var promise = injector.asyncGet(UserList);
|
||||
var ul = injector.get(UserList);
|
||||
|
||||
expect(promise).toBePromise();
|
||||
expect(ul).toBeAnInstanceOf(UserList);
|
||||
|
||||
promise.then(function(ful) {
|
||||
expect(ful).toBe(ul);
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should show the full path when error happens in a constructor',
|
||||
inject([AsyncTestCompleter], (async) => {
|
||||
var injector = Injector.resolveAndCreate([
|
||||
UserController,
|
||||
bind(UserList).toAsyncFactory(function() { throw "Broken UserList"; })
|
||||
]);
|
||||
|
||||
var promise = injector.asyncGet(UserController);
|
||||
PromiseWrapper.then(promise, null, function(e) {
|
||||
expect(e.message).toContain(
|
||||
`Error during instantiation of UserList! (${stringify(UserController)} -> UserList)`);
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
describe("get", function() {
|
||||
it('should throw when instantiating an async binding', function() {
|
||||
var injector = Injector.resolveAndCreate([bind(UserList).toAsyncFactory(fetchUsers)]);
|
||||
|
||||
expect(() => injector.get(UserList))
|
||||
.toThrowError(
|
||||
'Cannot instantiate UserList synchronously. It is provided as a promise!');
|
||||
});
|
||||
|
||||
it('should throw when instantiating a sync binding with an async dependency', function() {
|
||||
var injector =
|
||||
Injector.resolveAndCreate([bind(UserList).toAsyncFactory(fetchUsers), UserController]);
|
||||
|
||||
expect(() => injector.get(UserController))
|
||||
.toThrowError(new RegExp(
|
||||
'Cannot instantiate UserList synchronously. It is provided as a promise!'));
|
||||
});
|
||||
|
||||
it('should not throw when instantiating a sync binding with a resolved async dependency',
|
||||
inject([AsyncTestCompleter], (async) => {
|
||||
var injector = Injector.resolveAndCreate(
|
||||
[bind(UserList).toAsyncFactory(fetchUsers), UserController]);
|
||||
|
||||
injector.asyncGet(UserList).then((_) => {
|
||||
expect(() => { injector.get(UserController); }).not.toThrow();
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should resolve synchronously when an async dependency requested as a promise',
|
||||
function() {
|
||||
var injector = Injector.resolveAndCreate(
|
||||
[bind(UserList).toAsyncFactory(fetchUsers), AsyncUserController]);
|
||||
var controller = injector.get(AsyncUserController);
|
||||
|
||||
expect(controller).toBeAnInstanceOf(AsyncUserController);
|
||||
expect(controller.userList).toBePromise();
|
||||
});
|
||||
|
||||
it('should wrap sync dependencies into promises if required', function() {
|
||||
var injector = Injector.resolveAndCreate(
|
||||
[bind(UserList).toFactory(() => new UserList()), AsyncUserController]);
|
||||
var controller = injector.get(AsyncUserController);
|
||||
|
||||
expect(controller).toBeAnInstanceOf(AsyncUserController);
|
||||
expect(controller.userList).toBePromise();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -28,14 +28,10 @@ main() {
|
||||
expect(const Binding(Foo, toFactory: fn).toFactory).toBe(fn);
|
||||
});
|
||||
|
||||
it('can create constant from async factory', () {
|
||||
expect(const Binding(Foo, toAsyncFactory: fn).toAsyncFactory).toBe(fn);
|
||||
});
|
||||
|
||||
it('can be used in annotation', () {
|
||||
ClassMirror mirror = reflectType(Annotated);
|
||||
var bindings = mirror.metadata[0].reflectee.bindings;
|
||||
expect(bindings.length).toBe(6);
|
||||
expect(bindings.length).toBe(5);
|
||||
bindings.forEach((b) {
|
||||
expect(b).toBeA(Binding);
|
||||
});
|
||||
@@ -57,7 +53,6 @@ class Annotation {
|
||||
const Binding(Foo, toClass: Bar),
|
||||
const Binding(Foo, toValue: 5),
|
||||
const Binding(Foo, toAlias: Bar),
|
||||
const Binding(Foo, toFactory: fn),
|
||||
const Binding(Foo, toAsyncFactory: fn),
|
||||
const Binding(Foo, toFactory: fn)
|
||||
])
|
||||
class Annotated {}
|
||||
|
||||
@@ -9,13 +9,22 @@ import {
|
||||
DependencyAnnotation,
|
||||
Injectable
|
||||
} from 'angular2/di';
|
||||
import {Optional, Inject, InjectLazy} from 'angular2/src/di/decorators';
|
||||
import {Optional, Inject} from 'angular2/src/di/decorators';
|
||||
import * as ann from 'angular2/src/di/annotations_impl';
|
||||
|
||||
class CustomDependencyAnnotation extends DependencyAnnotation {}
|
||||
|
||||
class Engine {}
|
||||
|
||||
@Injectable(ann.self)
|
||||
class EngineWithSetVisibility {
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
class CarNeedsEngineWithSetVisibility {
|
||||
constructor(engine: EngineWithSetVisibility) {}
|
||||
}
|
||||
|
||||
class BrokenEngine {
|
||||
constructor() { throw new BaseException("Broken Engine"); }
|
||||
}
|
||||
@@ -35,12 +44,6 @@ class Car {
|
||||
constructor(engine: Engine) { this.engine = engine; }
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
class CarWithLazyEngine {
|
||||
engineFactory;
|
||||
constructor(@InjectLazy(Engine) engineFactory) { this.engineFactory = engineFactory; }
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
class CarWithOptionalEngine {
|
||||
engine;
|
||||
@@ -236,10 +239,6 @@ export function main() {
|
||||
expect(() => injector.get(Car))
|
||||
.toThrowError(
|
||||
`Cannot instantiate cyclic dependency! (${stringify(Car)} -> ${stringify(Engine)} -> ${stringify(Car)})`);
|
||||
|
||||
expect(() => injector.asyncGet(Car))
|
||||
.toThrowError(
|
||||
`Cannot instantiate cyclic dependency! (${stringify(Car)} -> ${stringify(Engine)} -> ${stringify(Car)})`);
|
||||
});
|
||||
|
||||
it('should show the full path when error happens in a constructor', () => {
|
||||
@@ -274,25 +273,6 @@ export function main() {
|
||||
expect(injector.get('null')).toBe(null);
|
||||
});
|
||||
|
||||
describe("default bindings", () => {
|
||||
it("should be used when no matching binding found", () => {
|
||||
var injector = Injector.resolveAndCreate([], {defaultBindings: true});
|
||||
|
||||
var car = injector.get(Car);
|
||||
|
||||
expect(car).toBeAnInstanceOf(Car);
|
||||
});
|
||||
|
||||
it("should use the matching binding when it is available", () => {
|
||||
var injector =
|
||||
Injector.resolveAndCreate([bind(Car).toClass(SportsCar)], {defaultBindings: true});
|
||||
|
||||
var car = injector.get(Car);
|
||||
|
||||
expect(car).toBeAnInstanceOf(SportsCar);
|
||||
});
|
||||
});
|
||||
|
||||
describe("child", () => {
|
||||
it('should load instances from parent injector', () => {
|
||||
var parent = Injector.resolveAndCreate([Engine]);
|
||||
@@ -324,17 +304,6 @@ export function main() {
|
||||
expect(engineFromChild).toBeAnInstanceOf(TurboEngine);
|
||||
});
|
||||
|
||||
it("should create child injectors without default bindings", () => {
|
||||
var parent = Injector.resolveAndCreate([], {defaultBindings: true});
|
||||
var child = parent.resolveAndCreateChild([]);
|
||||
|
||||
// child delegates to parent the creation of Car
|
||||
var childCar = child.get(Car);
|
||||
var parentCar = parent.get(Car);
|
||||
|
||||
expect(childCar).toBe(parentCar);
|
||||
});
|
||||
|
||||
it("should give access to direct parent", () => {
|
||||
var parent = Injector.resolveAndCreate([]);
|
||||
var child = parent.resolveAndCreateChild([]);
|
||||
@@ -342,25 +311,6 @@ export function main() {
|
||||
});
|
||||
});
|
||||
|
||||
describe("lazy", () => {
|
||||
it("should create dependencies lazily", () => {
|
||||
var injector = Injector.resolveAndCreate([Engine, CarWithLazyEngine]);
|
||||
|
||||
var car = injector.get(CarWithLazyEngine);
|
||||
expect(car.engineFactory()).toBeAnInstanceOf(Engine);
|
||||
});
|
||||
|
||||
it("should cache instance created lazily", () => {
|
||||
var injector = Injector.resolveAndCreate([Engine, CarWithLazyEngine]);
|
||||
|
||||
var car = injector.get(CarWithLazyEngine);
|
||||
var e1 = car.engineFactory();
|
||||
var e2 = car.engineFactory();
|
||||
|
||||
expect(e1).toBe(e2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('resolve', () => {
|
||||
it('should resolve and flatten', () => {
|
||||
var bindings = Injector.resolve([Engine, [BrokenEngine]]);
|
||||
@@ -374,20 +324,16 @@ export function main() {
|
||||
var bindings = Injector.resolve([
|
||||
forwardRef(() => Engine),
|
||||
[bind(forwardRef(() => BrokenEngine)).toClass(forwardRef(() => Engine))],
|
||||
bind(forwardRef(() => String)).toFactory(() => 'OK', [forwardRef(() => Engine)]),
|
||||
bind(forwardRef(() => DashboardSoftware))
|
||||
.toAsyncFactory(() => 123, [forwardRef(() => BrokenEngine)])
|
||||
bind(forwardRef(() => String)).toFactory(() => 'OK', [forwardRef(() => Engine)])
|
||||
]);
|
||||
|
||||
var engineBinding = bindings[Key.get(Engine).id];
|
||||
var brokenEngineBinding = bindings[Key.get(BrokenEngine).id];
|
||||
var stringBinding = bindings[Key.get(String).id];
|
||||
var dashboardSoftwareBinding = bindings[Key.get(DashboardSoftware).id];
|
||||
var engineBinding = bindings[0];
|
||||
var brokenEngineBinding = bindings[1];
|
||||
var stringBinding = bindings[2];
|
||||
|
||||
expect(engineBinding.factory() instanceof Engine).toBe(true);
|
||||
expect(brokenEngineBinding.factory() instanceof Engine).toBe(true);
|
||||
expect(stringBinding.dependencies[0].key).toEqual(Key.get(Engine));
|
||||
expect(dashboardSoftwareBinding.dependencies[0].key).toEqual(Key.get(BrokenEngine));
|
||||
});
|
||||
|
||||
it('should support overriding factory dependencies with dependency annotations', () => {
|
||||
@@ -396,11 +342,25 @@ export function main() {
|
||||
.toFactory((e) => "result",
|
||||
[[new ann.Inject("dep"), new CustomDependencyAnnotation()]])
|
||||
]);
|
||||
var binding = bindings[Key.get("token").id];
|
||||
var binding = bindings[0];
|
||||
|
||||
expect(binding.dependencies[0].key.token).toEqual("dep");
|
||||
expect(binding.dependencies[0].properties).toEqual([new CustomDependencyAnnotation()]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("default visibility", () => {
|
||||
it("should use the provided visibility", () => {
|
||||
var bindings = Injector.resolve([CarNeedsEngineWithSetVisibility, EngineWithSetVisibility]);
|
||||
var carBinding = bindings[0];
|
||||
expect(carBinding.dependencies[0].visibility).toEqual(ann.self);
|
||||
});
|
||||
|
||||
it("should set the default visibility to unbounded", () => {
|
||||
var bindings = Injector.resolve([Car, Engine]);
|
||||
var carBinding = bindings[0];
|
||||
expect(carBinding.dependencies[0].visibility).toEqual(ann.unbounded);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ export function main() {
|
||||
var router = applicationRef.hostComponent.router;
|
||||
PromiseWrapper.catchError(router.navigate('/cause-error'), (error) => {
|
||||
expect(el).toHaveText('outer { oh no }');
|
||||
expect(error.message).toBe('oops!');
|
||||
expect(error.message).toContain('oops!');
|
||||
async.done();
|
||||
});
|
||||
});
|
||||
@@ -89,7 +89,6 @@ export function main() {
|
||||
router.navigate('/parent/child');
|
||||
});
|
||||
}));
|
||||
|
||||
// TODO: add a test in which the child component has bindings
|
||||
});
|
||||
}
|
||||
@@ -107,14 +106,12 @@ class AppCmp {
|
||||
constructor(public router: Router, public location: LocationStrategy) {}
|
||||
}
|
||||
|
||||
|
||||
@Component({selector: 'parent-cmp'})
|
||||
@View({template: `parent { <router-outlet></router-outlet> }`, directives: routerDirectives})
|
||||
@RouteConfig([{path: '/child', component: HelloCmp}])
|
||||
class ParentCmp {
|
||||
}
|
||||
|
||||
|
||||
@Component({selector: 'app-cmp'})
|
||||
@View({template: `root { <router-outlet></router-outlet> }`, directives: routerDirectives})
|
||||
@RouteConfig([{path: '/parent/...', component: ParentCmp}])
|
||||
|
||||
Reference in New Issue
Block a user