feat(ElementInjector): support an arbitrary number of bindings
fixes #1853
This commit is contained in:
parent
588fbfd848
commit
b1c9bf14b2
File diff suppressed because it is too large
Load Diff
|
@ -211,6 +211,13 @@ export function main() {
|
||||||
var defaultPreBuiltObjects = new PreBuiltObjects(null, null, null);
|
var defaultPreBuiltObjects = new PreBuiltObjects(null, null, null);
|
||||||
var appInjector = Injector.resolveAndCreate([]);
|
var appInjector = Injector.resolveAndCreate([]);
|
||||||
|
|
||||||
|
// An injector with more than 10 bindings will switch to the dynamic strategy
|
||||||
|
var dynamicBindings = [];
|
||||||
|
|
||||||
|
for (var i = 0; i < 20; i++) {
|
||||||
|
ListWrapper.push(dynamicBindings, bind(i).toValue(i));
|
||||||
|
}
|
||||||
|
|
||||||
function createPei(parent, index, bindings, distance = 1, hasShadowRoot = false) {
|
function createPei(parent, index, bindings, distance = 1, hasShadowRoot = false) {
|
||||||
var directiveBinding = ListWrapper.map(bindings, b => {
|
var directiveBinding = ListWrapper.map(bindings, b => {
|
||||||
if (b instanceof DirectiveBinding) return b;
|
if (b instanceof DirectiveBinding) return b;
|
||||||
|
@ -350,8 +357,6 @@ export function main() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
describe("ProtoElementInjector", () => {
|
describe("ProtoElementInjector", () => {
|
||||||
describe("direct parent", () => {
|
describe("direct parent", () => {
|
||||||
it("should return parent proto injector when distance is 1", () => {
|
it("should return parent proto injector when distance is 1", () => {
|
||||||
|
@ -370,10 +375,11 @@ export function main() {
|
||||||
expect(protoChild.directParent()).toEqual(null);
|
expect(protoChild.directParent()).toEqual(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should allow for direct access using getBindingAtIndex", function () {
|
});
|
||||||
var binding = DirectiveBinding.createFromBinding(
|
|
||||||
bind(SimpleDirective).toClass(SimpleDirective), null);
|
describe('inline strategy', () => {
|
||||||
var proto = createPei(null, 0, [binding]);
|
it("should allow for direct access using getBindingAtIndex", () => {
|
||||||
|
var proto = createPei(null, 0, [bind(SimpleDirective).toClass(SimpleDirective)]);
|
||||||
|
|
||||||
expect(proto.getBindingAtIndex(0)).toBeAnInstanceOf(DirectiveBinding);
|
expect(proto.getBindingAtIndex(0)).toBeAnInstanceOf(DirectiveBinding);
|
||||||
expect(() => proto.getBindingAtIndex(-1)).toThrowError(
|
expect(() => proto.getBindingAtIndex(-1)).toThrowError(
|
||||||
|
@ -383,6 +389,19 @@ export function main() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('dynamic strategy', () => {
|
||||||
|
it("should allow for direct access using getBindingAtIndex", () => {
|
||||||
|
var proto = createPei(null, 0, dynamicBindings);
|
||||||
|
|
||||||
|
expect(proto.getBindingAtIndex(0)).toBeAnInstanceOf(DirectiveBinding);
|
||||||
|
expect(() => proto.getBindingAtIndex(-1)).toThrowError(
|
||||||
|
'Index -1 is out-of-bounds.');
|
||||||
|
expect(() => proto.getBindingAtIndex(dynamicBindings.length - 1)).not.toThrow();
|
||||||
|
expect(() => proto.getBindingAtIndex(dynamicBindings.length)).toThrowError(
|
||||||
|
`Index ${dynamicBindings.length} is out-of-bounds.`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('event emitters', () => {
|
describe('event emitters', () => {
|
||||||
it('should return a list of event accessors', () => {
|
it('should return a list of event accessors', () => {
|
||||||
var binding = DirectiveBinding.createFromType(
|
var binding = DirectiveBinding.createFromType(
|
||||||
|
@ -434,12 +453,21 @@ export function main() {
|
||||||
expect(pei.getBindingAtIndex(0).key.token).toBe(SimpleDirective);
|
expect(pei.getBindingAtIndex(0).key.token).toBe(SimpleDirective);
|
||||||
expect(pei.getBindingAtIndex(1).key.token).toEqual("injectable1");
|
expect(pei.getBindingAtIndex(1).key.token).toEqual("injectable1");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should support an arbitrary number of bindings', () => {
|
||||||
|
var pei = createPei(null, 0, dynamicBindings);
|
||||||
|
|
||||||
|
for (var i = 0; i < dynamicBindings.length; i++) {
|
||||||
|
expect(pei.getBindingAtIndex(i).key.token).toBe(i);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("ElementInjector", function () {
|
});
|
||||||
describe("instantiate", function () {
|
|
||||||
it("should create an element injector", function () {
|
describe("ElementInjector", () => {
|
||||||
|
describe("instantiate", () => {
|
||||||
|
it("should create an element injector", () => {
|
||||||
var protoParent = createPei(null, 0, []);
|
var protoParent = createPei(null, 0, []);
|
||||||
var protoChild1 = createPei(protoParent, 1, []);
|
var protoChild1 = createPei(protoParent, 1, []);
|
||||||
var protoChild2 = createPei(protoParent, 2, []);
|
var protoChild2 = createPei(protoParent, 2, []);
|
||||||
|
@ -480,36 +508,44 @@ export function main() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("hasBindings", function () {
|
describe("hasBindings", () => {
|
||||||
it("should be true when there are bindings", function () {
|
it("should be true when there are bindings", () => {
|
||||||
var p = createPei(null, 0, [SimpleDirective]);
|
var p = createPei(null, 0, [SimpleDirective]);
|
||||||
expect(p.hasBindings).toBeTruthy();
|
expect(p.hasBindings).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should be false otherwise", function () {
|
it("should be false otherwise", () => {
|
||||||
var p = createPei(null, 0, []);
|
var p = createPei(null, 0, []);
|
||||||
expect(p.hasBindings).toBeFalsy();
|
expect(p.hasBindings).toBeFalsy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("hasInstances", function () {
|
describe("hasInstances", () => {
|
||||||
it("should be false when no directives are instantiated", function () {
|
it("should be false when no directives are instantiated", () => {
|
||||||
expect(injector([]).hasInstances()).toBe(false);
|
expect(injector([]).hasInstances()).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should be true when directives are instantiated", function () {
|
it("should be true when directives are instantiated", () => {
|
||||||
expect(injector([SimpleDirective]).hasInstances()).toBe(true);
|
expect(injector([SimpleDirective]).hasInstances()).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("hydrate", function () {
|
[
|
||||||
it("should instantiate directives that have no dependencies", function () {
|
{ strategy: 'inline', bindings: []},
|
||||||
var inj = injector([SimpleDirective]);
|
{ strategy: 'dynamic', bindings: dynamicBindings}
|
||||||
|
].forEach((context) => {
|
||||||
|
var extraBindings = context['bindings'];
|
||||||
|
describe(`${context['strategy']} strategy`, () => {
|
||||||
|
describe("hydrate", () => {
|
||||||
|
it("should instantiate directives that have no dependencies", () => {
|
||||||
|
var bindings = ListWrapper.concat([SimpleDirective], extraBindings);
|
||||||
|
var inj = injector(bindings);
|
||||||
expect(inj.get(SimpleDirective)).toBeAnInstanceOf(SimpleDirective);
|
expect(inj.get(SimpleDirective)).toBeAnInstanceOf(SimpleDirective);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should instantiate directives that depend on other directives", function () {
|
it("should instantiate directives that depend on an arbitrary number of directives", () => {
|
||||||
var inj = injector([SimpleDirective, NeedsDirective]);
|
var bindings = ListWrapper.concat([SimpleDirective, NeedsDirective], extraBindings);
|
||||||
|
var inj = injector(bindings);
|
||||||
|
|
||||||
var d = inj.get(NeedsDirective);
|
var d = inj.get(NeedsDirective);
|
||||||
|
|
||||||
|
@ -517,24 +553,14 @@ export function main() {
|
||||||
expect(d.dependency).toBeAnInstanceOf(SimpleDirective);
|
expect(d.dependency).toBeAnInstanceOf(SimpleDirective);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should instantiate hostInjector injectables that have dependencies", function () {
|
|
||||||
var inj = injector([
|
|
||||||
DirectiveBinding.createFromType(SimpleDirective,
|
|
||||||
new DummyDirective({hostInjector: [
|
|
||||||
bind('injectable1').toValue('injectable1'),
|
|
||||||
bind('injectable2').toFactory((val) => `${val}-injectable2`, ['injectable1'])
|
|
||||||
]}))
|
|
||||||
]);
|
|
||||||
expect(inj.get('injectable2')).toEqual('injectable1-injectable2');
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should instantiate hostInjector injectables that have dependencies with set visibility", function () {
|
it("should instantiate hostInjector injectables that have dependencies with set visibility", function () {
|
||||||
var childInj= parentChildInjectors([
|
var childInj= parentChildInjectors(ListWrapper.concat([
|
||||||
DirectiveBinding.createFromType(SimpleDirective,
|
DirectiveBinding.createFromType(SimpleDirective,
|
||||||
new DummyDirective({hostInjector: [
|
new DummyDirective({hostInjector: [
|
||||||
bind('injectable1').toValue('injectable1')
|
bind('injectable1').toValue('injectable1')
|
||||||
]}))
|
]}))
|
||||||
], [
|
], extraBindings), [
|
||||||
DirectiveBinding.createFromType(SimpleDirective,
|
DirectiveBinding.createFromType(SimpleDirective,
|
||||||
new DummyDirective({hostInjector: [
|
new DummyDirective({hostInjector: [
|
||||||
bind('injectable1').toValue('new-injectable1'),
|
bind('injectable1').toValue('new-injectable1'),
|
||||||
|
@ -554,10 +580,32 @@ export function main() {
|
||||||
expect(inj.get(NeedsService).service).toEqual('service');
|
expect(inj.get(NeedsService).service).toEqual('service');
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should instantiate directives that depend on app services", function () {
|
it("should instantiate hostInjector injectables that have dependencies", () => {
|
||||||
var appInjector = Injector.resolveAndCreate([
|
var inj = injector(ListWrapper.concat([
|
||||||
bind("service").toValue("service")
|
DirectiveBinding.createFromType(SimpleDirective,
|
||||||
]);
|
new DummyDirective({hostInjector: [
|
||||||
|
bind('injectable1').toValue('injectable1'),
|
||||||
|
bind('injectable2').toFactory((val) => `${val}-injectable2`, ['injectable1'])
|
||||||
|
]}))],
|
||||||
|
extraBindings
|
||||||
|
));
|
||||||
|
expect(inj.get('injectable2')).toEqual('injectable1-injectable2');
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should instantiate components that depends on viewInjector dependencies", function () {
|
||||||
|
var inj = injector(ListWrapper.concat([
|
||||||
|
DirectiveBinding.createFromType(NeedsService,
|
||||||
|
new DummyDirective({viewInjector: [
|
||||||
|
bind('service').toValue('service')
|
||||||
|
]}))],
|
||||||
|
extraBindings),
|
||||||
|
null, true);
|
||||||
|
expect(inj.get(NeedsService).service).toEqual('service');
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should instantiate directives that depend on app services", () => {
|
||||||
|
var appInjector = Injector.resolveAndCreate(ListWrapper.concat([
|
||||||
|
bind("service").toValue("service")], extraBindings));
|
||||||
var inj = injector([NeedsService], appInjector);
|
var inj = injector([NeedsService], appInjector);
|
||||||
|
|
||||||
var d = inj.get(NeedsService);
|
var d = inj.get(NeedsService);
|
||||||
|
@ -565,24 +613,27 @@ export function main() {
|
||||||
expect(d.service).toEqual("service");
|
expect(d.service).toEqual("service");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should instantiate directives that depend on pre built objects", function () {
|
it("should instantiate directives that depend on pre built objects", () => {
|
||||||
var protoView = new AppProtoView(null, null, null);
|
var protoView = new AppProtoView(null, null, null);
|
||||||
var inj = injector([NeedsProtoViewRef], null, false, new PreBuiltObjects(null, null, protoView));
|
var bindings = ListWrapper.concat([NeedsProtoViewRef], extraBindings);
|
||||||
|
var inj = injector(bindings, null, false, new PreBuiltObjects(null, null, protoView));
|
||||||
|
|
||||||
expect(inj.get(NeedsProtoViewRef).protoViewRef).toEqual(new ProtoViewRef(protoView));
|
expect(inj.get(NeedsProtoViewRef).protoViewRef).toEqual(new ProtoViewRef(protoView));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return app services", function () {
|
it("should return app services", () => {
|
||||||
var appInjector = Injector.resolveAndCreate([
|
var appInjector = Injector.resolveAndCreate(ListWrapper.concat([
|
||||||
bind("service").toValue("service")
|
bind("service").toValue("service")], extraBindings
|
||||||
]);
|
));
|
||||||
var inj = injector([], appInjector);
|
var inj = injector([], appInjector);
|
||||||
|
|
||||||
expect(inj.get('service')).toEqual('service');
|
expect(inj.get('service')).toEqual('service');
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should get directives from parent", function () {
|
it("should get directives from parent", () => {
|
||||||
var child = parentChildInjectors([SimpleDirective], [NeedsDirectiveFromParent]);
|
var child = parentChildInjectors(
|
||||||
|
ListWrapper.concat([SimpleDirective], extraBindings),
|
||||||
|
[NeedsDirectiveFromParent]);
|
||||||
|
|
||||||
var d = child.get(NeedsDirectiveFromParent);
|
var d = child.get(NeedsDirectiveFromParent);
|
||||||
|
|
||||||
|
@ -590,14 +641,17 @@ export function main() {
|
||||||
expect(d.dependency).toBeAnInstanceOf(SimpleDirective);
|
expect(d.dependency).toBeAnInstanceOf(SimpleDirective);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not return parent's directives on self", function () {
|
it("should not return parent's directives on self", () => {
|
||||||
expect(() => {
|
expect(() => {
|
||||||
injector([SimpleDirective, NeedsDirectiveFromParent]);
|
injector(ListWrapper.concat(
|
||||||
|
[SimpleDirective, NeedsDirectiveFromParent], extraBindings));
|
||||||
}).toThrowError(new RegExp("No provider for SimpleDirective"));
|
}).toThrowError(new RegExp("No provider for SimpleDirective"));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should get directives from ancestor", function () {
|
it("should get directives from ancestor", () => {
|
||||||
var child = parentChildInjectors([SimpleDirective], [NeedsDirectiveFromAncestor]);
|
var child = parentChildInjectors(
|
||||||
|
ListWrapper.concat([SimpleDirective], extraBindings),
|
||||||
|
[NeedsDirectiveFromAncestor]);
|
||||||
|
|
||||||
var d = child.get(NeedsDirectiveFromAncestor);
|
var d = child.get(NeedsDirectiveFromAncestor);
|
||||||
|
|
||||||
|
@ -605,8 +659,9 @@ export function main() {
|
||||||
expect(d.dependency).toBeAnInstanceOf(SimpleDirective);
|
expect(d.dependency).toBeAnInstanceOf(SimpleDirective);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should get directives crossing the boundaries", function () {
|
it("should get directives crossing the boundaries", () => {
|
||||||
var child = hostShadowInjectors([SomeOtherDirective, SimpleDirective],
|
var child = hostShadowInjectors(
|
||||||
|
ListWrapper.concat([SomeOtherDirective, SimpleDirective], extraBindings),
|
||||||
[NeedsDirectiveFromAnAncestorShadowDom]);
|
[NeedsDirectiveFromAnAncestorShadowDom]);
|
||||||
|
|
||||||
var d = child.get(NeedsDirectiveFromAnAncestorShadowDom);
|
var d = child.get(NeedsDirectiveFromAnAncestorShadowDom);
|
||||||
|
@ -615,52 +670,59 @@ export function main() {
|
||||||
expect(d.dependency).toBeAnInstanceOf(SimpleDirective);
|
expect(d.dependency).toBeAnInstanceOf(SimpleDirective);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should throw when a depenency cannot be resolved", function () {
|
it("should throw when a depenency cannot be resolved", () => {
|
||||||
expect(() => injector([NeedsDirectiveFromParent])).
|
expect(() => injector(ListWrapper.concat([NeedsDirectiveFromParent], extraBindings))).
|
||||||
toThrowError('No provider for SimpleDirective! (NeedsDirectiveFromParent -> SimpleDirective)');
|
toThrowError('No provider for SimpleDirective! (NeedsDirectiveFromParent -> SimpleDirective)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should inject null when an optional dependency cannot be resolved", function () {
|
it("should inject null when an optional dependency cannot be resolved", () => {
|
||||||
var inj = injector([OptionallyNeedsDirective]);
|
var inj = injector(ListWrapper.concat([OptionallyNeedsDirective], extraBindings));
|
||||||
var d = inj.get(OptionallyNeedsDirective);
|
var d = inj.get(OptionallyNeedsDirective);
|
||||||
expect(d.dependency).toEqual(null);
|
expect(d.dependency).toEqual(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should accept bindings instead types", function () {
|
it("should accept bindings instead types", () => {
|
||||||
var inj = injector([
|
var inj = injector(ListWrapper.concat([
|
||||||
DirectiveBinding.createFromBinding(bind(SimpleDirective).toClass(SimpleDirective), null)
|
bind(SimpleDirective).toClass(SimpleDirective)],
|
||||||
]);
|
extraBindings
|
||||||
|
));
|
||||||
expect(inj.get(SimpleDirective)).toBeAnInstanceOf(SimpleDirective);
|
expect(inj.get(SimpleDirective)).toBeAnInstanceOf(SimpleDirective);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should allow for direct access using getDirectiveAtIndex", function () {
|
it("should allow for direct access using getDirectiveAtIndex", () => {
|
||||||
var inj = injector([
|
var bindings = ListWrapper.concat([
|
||||||
DirectiveBinding.createFromBinding(bind(SimpleDirective).toClass(SimpleDirective), null)
|
bind(SimpleDirective).toClass(SimpleDirective)],
|
||||||
]);
|
extraBindings
|
||||||
|
);
|
||||||
|
|
||||||
|
var inj = injector(bindings);
|
||||||
|
|
||||||
|
var firsIndexOut = bindings.length > 10 ? bindings.length : 10;
|
||||||
|
|
||||||
expect(inj.getDirectiveAtIndex(0)).toBeAnInstanceOf(SimpleDirective);
|
expect(inj.getDirectiveAtIndex(0)).toBeAnInstanceOf(SimpleDirective);
|
||||||
expect(() => inj.getDirectiveAtIndex(-1)).toThrowError(
|
expect(() => inj.getDirectiveAtIndex(-1)).toThrowError(
|
||||||
'Index -1 is out-of-bounds.');
|
'Index -1 is out-of-bounds.');
|
||||||
expect(() => inj.getDirectiveAtIndex(10)).toThrowError(
|
expect(() => inj.getDirectiveAtIndex(firsIndexOut)).toThrowError(
|
||||||
'Index 10 is out-of-bounds.');
|
`Index ${firsIndexOut} is out-of-bounds.`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it("should handle cyclic dependencies", function () {
|
it("should handle cyclic dependencies", () => {
|
||||||
expect(() => {
|
expect(() => {
|
||||||
var bAneedsB = bind(A_Needs_B).toFactory((a) => new A_Needs_B(a), [B_Needs_A]);
|
var bAneedsB = bind(A_Needs_B).toFactory((a) => new A_Needs_B(a), [B_Needs_A]);
|
||||||
var bBneedsA = bind(B_Needs_A).toFactory((a) => new B_Needs_A(a), [A_Needs_B]);
|
var bBneedsA = bind(B_Needs_A).toFactory((a) => new B_Needs_A(a), [A_Needs_B]);
|
||||||
injector([
|
|
||||||
DirectiveBinding.createFromBinding(bAneedsB, null),
|
injector(ListWrapper.concat([bAneedsB, bBneedsA], extraBindings));
|
||||||
DirectiveBinding.createFromBinding(bBneedsA, null)
|
|
||||||
]);
|
|
||||||
}).toThrowError('Cannot instantiate cyclic dependency! ' +
|
}).toThrowError('Cannot instantiate cyclic dependency! ' +
|
||||||
'(A_Needs_B -> B_Needs_A -> A_Needs_B)');
|
'(A_Needs_B -> B_Needs_A -> A_Needs_B)');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("shadow DOM components", () => {
|
describe("shadow DOM components", () => {
|
||||||
it("should instantiate directives that depend on the containing component", function () {
|
it("should instantiate directives that depend on the containing component", () => {
|
||||||
var directiveBinding = DirectiveBinding.createFromType(SimpleDirective, new Component());
|
var directiveBinding = DirectiveBinding.createFromType(SimpleDirective, new Component());
|
||||||
var shadow = hostShadowInjectors([directiveBinding], [NeedsDirective]);
|
var shadow = hostShadowInjectors(
|
||||||
|
ListWrapper.concat([directiveBinding], extraBindings),
|
||||||
|
[NeedsDirective]);
|
||||||
|
|
||||||
var d = shadow.get(NeedsDirective);
|
var d = shadow.get(NeedsDirective);
|
||||||
expect(d).toBeAnInstanceOf(NeedsDirective);
|
expect(d).toBeAnInstanceOf(NeedsDirective);
|
||||||
|
@ -670,15 +732,18 @@ export function main() {
|
||||||
it("should not instantiate directives that depend on other directives in the containing component's ElementInjector", () => {
|
it("should not instantiate directives that depend on other directives in the containing component's ElementInjector", () => {
|
||||||
var directiveBinding = DirectiveBinding.createFromType(SomeOtherDirective, new Component());
|
var directiveBinding = DirectiveBinding.createFromType(SomeOtherDirective, new Component());
|
||||||
expect(() => {
|
expect(() => {
|
||||||
hostShadowInjectors([directiveBinding, SimpleDirective],[NeedsDirective]);
|
hostShadowInjectors(
|
||||||
|
ListWrapper.concat([directiveBinding, SimpleDirective], extraBindings),
|
||||||
|
[NeedsDirective]);
|
||||||
}).toThrowError('No provider for SimpleDirective! (NeedsDirective -> SimpleDirective)');
|
}).toThrowError('No provider for SimpleDirective! (NeedsDirective -> SimpleDirective)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should instantiate component directives that depend on app services in the shadow app injector", () => {
|
it("should instantiate component directives that depend on app services in the shadow app injector", () => {
|
||||||
var directiveAnnotation = new Component({
|
var directiveAnnotation = new Component({
|
||||||
appInjector: [
|
appInjector: ListWrapper.concat([
|
||||||
bind("service").toValue("service")
|
bind("service").toValue("service")],
|
||||||
]
|
extraBindings
|
||||||
|
)
|
||||||
});
|
});
|
||||||
var componentDirective = DirectiveBinding.createFromType(
|
var componentDirective = DirectiveBinding.createFromType(
|
||||||
NeedsService, directiveAnnotation);
|
NeedsService, directiveAnnotation);
|
||||||
|
@ -691,9 +756,10 @@ export function main() {
|
||||||
|
|
||||||
it("should not instantiate other directives that depend on app services in the shadow app injector", () => {
|
it("should not instantiate other directives that depend on app services in the shadow app injector", () => {
|
||||||
var directiveAnnotation = new Component({
|
var directiveAnnotation = new Component({
|
||||||
appInjector: [
|
appInjector: ListWrapper.concat([
|
||||||
bind("service").toValue("service")
|
bind("service").toValue("service")],
|
||||||
]
|
extraBindings
|
||||||
|
)
|
||||||
});
|
});
|
||||||
var componentDirective = DirectiveBinding.createFromType(SimpleDirective, directiveAnnotation);
|
var componentDirective = DirectiveBinding.createFromType(SimpleDirective, directiveAnnotation);
|
||||||
expect(() => {
|
expect(() => {
|
||||||
|
@ -705,21 +771,27 @@ export function main() {
|
||||||
|
|
||||||
describe("lifecycle", () => {
|
describe("lifecycle", () => {
|
||||||
it("should call onDestroy on directives subscribed to this event", function() {
|
it("should call onDestroy on directives subscribed to this event", function() {
|
||||||
var inj = injector([DirectiveBinding.createFromType(DirectiveWithDestroy, new DummyDirective({lifecycle: [onDestroy]}))]);
|
var inj = injector(ListWrapper.concat([
|
||||||
|
DirectiveBinding.createFromType(DirectiveWithDestroy, new DummyDirective({lifecycle: [onDestroy]}))],
|
||||||
|
extraBindings
|
||||||
|
));
|
||||||
var destroy = inj.get(DirectiveWithDestroy);
|
var destroy = inj.get(DirectiveWithDestroy);
|
||||||
inj.dehydrate();
|
inj.dehydrate();
|
||||||
expect(destroy.onDestroyCounter).toBe(1);
|
expect(destroy.onDestroyCounter).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should work with services", function() {
|
it("should work with services", function() {
|
||||||
var inj = injector([DirectiveBinding.createFromType(SimpleDirective, new DummyDirective({hostInjector: [SimpleService]}))]);
|
var inj = injector(ListWrapper.concat([
|
||||||
|
DirectiveBinding.createFromType(SimpleDirective, new DummyDirective({hostInjector: [SimpleService]}))],
|
||||||
|
extraBindings
|
||||||
|
));
|
||||||
inj.dehydrate();
|
inj.dehydrate();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("dynamicallyCreateComponent", () => {
|
describe("dynamicallyCreateComponent", () => {
|
||||||
it("should create a component dynamically", () => {
|
it("should create a component dynamically", () => {
|
||||||
var inj = injector([]);
|
var inj = injector(extraBindings);
|
||||||
|
|
||||||
inj.dynamicallyCreateComponent(DirectiveBinding.createFromType(SimpleDirective, null), appInjector);
|
inj.dynamicallyCreateComponent(DirectiveBinding.createFromType(SimpleDirective, null), appInjector);
|
||||||
expect(inj.getDynamicallyLoadedComponent()).toBeAnInstanceOf(SimpleDirective);
|
expect(inj.getDynamicallyLoadedComponent()).toBeAnInstanceOf(SimpleDirective);
|
||||||
|
@ -727,7 +799,9 @@ export function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should inject parent dependencies into the dynamically-loaded component", () => {
|
it("should inject parent dependencies into the dynamically-loaded component", () => {
|
||||||
var inj = parentChildInjectors([SimpleDirective], []);
|
var inj = parentChildInjectors(
|
||||||
|
ListWrapper.concat([SimpleDirective], extraBindings),
|
||||||
|
[]);
|
||||||
inj.dynamicallyCreateComponent(DirectiveBinding.createFromType(NeedsDirectiveFromAncestor, null), appInjector);
|
inj.dynamicallyCreateComponent(DirectiveBinding.createFromType(NeedsDirectiveFromAncestor, null), appInjector);
|
||||||
expect(inj.getDynamicallyLoadedComponent()).toBeAnInstanceOf(NeedsDirectiveFromAncestor);
|
expect(inj.getDynamicallyLoadedComponent()).toBeAnInstanceOf(NeedsDirectiveFromAncestor);
|
||||||
expect(inj.getDynamicallyLoadedComponent().dependency).toBeAnInstanceOf(SimpleDirective);
|
expect(inj.getDynamicallyLoadedComponent().dependency).toBeAnInstanceOf(SimpleDirective);
|
||||||
|
@ -737,7 +811,8 @@ export function main() {
|
||||||
var injWithDynamicallyLoadedComponent = injector([SimpleDirective]);
|
var injWithDynamicallyLoadedComponent = injector([SimpleDirective]);
|
||||||
injWithDynamicallyLoadedComponent.dynamicallyCreateComponent(DirectiveBinding.createFromType(SomeOtherDirective, null), appInjector);
|
injWithDynamicallyLoadedComponent.dynamicallyCreateComponent(DirectiveBinding.createFromType(SomeOtherDirective, null), appInjector);
|
||||||
|
|
||||||
var shadowDomProtoInjector = createPei(null, 0, [NeedsDirectiveFromAncestor]);
|
var shadowDomProtoInjector = createPei(
|
||||||
|
null, 0, ListWrapper.concat([NeedsDirectiveFromAncestor], extraBindings));
|
||||||
var shadowDomInj = shadowDomProtoInjector.instantiate(null);
|
var shadowDomInj = shadowDomProtoInjector.instantiate(null);
|
||||||
|
|
||||||
expect(() =>
|
expect(() =>
|
||||||
|
@ -747,7 +822,8 @@ export function main() {
|
||||||
|
|
||||||
it("should not inject the dynamically-loaded component into directives on the same element", () => {
|
it("should not inject the dynamically-loaded component into directives on the same element", () => {
|
||||||
var dynamicComp = DirectiveBinding.createFromType(SomeOtherDirective, new Component());
|
var dynamicComp = DirectiveBinding.createFromType(SomeOtherDirective, new Component());
|
||||||
var proto = createPei(null, 0, [dynamicComp, NeedsDirective], 1, true);
|
var proto = createPei(
|
||||||
|
null, 0, ListWrapper.concat([dynamicComp, NeedsDirective], extraBindings), 1, true);
|
||||||
var inj = proto.instantiate(null);
|
var inj = proto.instantiate(null);
|
||||||
inj.dynamicallyCreateComponent(
|
inj.dynamicallyCreateComponent(
|
||||||
DirectiveBinding.createFromType(SimpleDirective, null), appInjector);
|
DirectiveBinding.createFromType(SimpleDirective, null), appInjector);
|
||||||
|
@ -767,7 +843,8 @@ export function main() {
|
||||||
var injWithDynamicallyLoadedComponent = injector([]);
|
var injWithDynamicallyLoadedComponent = injector([]);
|
||||||
injWithDynamicallyLoadedComponent.dynamicallyCreateComponent(componentDirective, appInjector);
|
injWithDynamicallyLoadedComponent.dynamicallyCreateComponent(componentDirective, appInjector);
|
||||||
|
|
||||||
var shadowDomProtoInjector = createPei(null, 0, [NeedsDirectiveFromAncestor]);
|
var shadowDomProtoInjector = createPei(
|
||||||
|
null, 0, ListWrapper.concat([NeedsDirectiveFromAncestor], extraBindings));
|
||||||
var shadowDomInjector = shadowDomProtoInjector.instantiate(null);
|
var shadowDomInjector = shadowDomProtoInjector.instantiate(null);
|
||||||
shadowDomInjector.hydrate(appInjector, injWithDynamicallyLoadedComponent, defaultPreBuiltObjects);
|
shadowDomInjector.hydrate(appInjector, injWithDynamicallyLoadedComponent, defaultPreBuiltObjects);
|
||||||
|
|
||||||
|
@ -776,7 +853,7 @@ export function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should remove the dynamically-loaded component when dehydrating", () => {
|
it("should remove the dynamically-loaded component when dehydrating", () => {
|
||||||
var inj = injector([]);
|
var inj = injector(extraBindings);
|
||||||
inj.dynamicallyCreateComponent(
|
inj.dynamicallyCreateComponent(
|
||||||
DirectiveBinding.createFromType(
|
DirectiveBinding.createFromType(
|
||||||
DirectiveWithDestroy,
|
DirectiveWithDestroy,
|
||||||
|
@ -796,7 +873,7 @@ export function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should inject services of the dynamically-loaded component", () => {
|
it("should inject services of the dynamically-loaded component", () => {
|
||||||
var inj = injector([]);
|
var inj = injector(extraBindings);
|
||||||
var appInjector = Injector.resolveAndCreate([bind("service").toValue("Service")]);
|
var appInjector = Injector.resolveAndCreate([bind("service").toValue("Service")]);
|
||||||
inj.dynamicallyCreateComponent(DirectiveBinding.createFromType(NeedsService, null), appInjector);
|
inj.dynamicallyCreateComponent(DirectiveBinding.createFromType(NeedsService, null), appInjector);
|
||||||
expect(inj.getDynamicallyLoadedComponent().service).toEqual("Service");
|
expect(inj.getDynamicallyLoadedComponent().service).toEqual("Service");
|
||||||
|
@ -809,7 +886,8 @@ export function main() {
|
||||||
MapWrapper.set(attributes, 'type', 'text');
|
MapWrapper.set(attributes, 'type', 'text');
|
||||||
MapWrapper.set(attributes, 'title', '');
|
MapWrapper.set(attributes, 'title', '');
|
||||||
|
|
||||||
var inj = injector([NeedsAttribute], null, false, null, attributes);
|
var inj = injector(
|
||||||
|
ListWrapper.concat([NeedsAttribute], extraBindings), null, false, null, attributes);
|
||||||
var needsAttribute = inj.get(NeedsAttribute);
|
var needsAttribute = inj.get(NeedsAttribute);
|
||||||
|
|
||||||
expect(needsAttribute.typeAttribute).toEqual('text');
|
expect(needsAttribute.typeAttribute).toEqual('text');
|
||||||
|
@ -821,7 +899,8 @@ export function main() {
|
||||||
var attributes = MapWrapper.create();
|
var attributes = MapWrapper.create();
|
||||||
MapWrapper.set(attributes, 'foo', 'bar');
|
MapWrapper.set(attributes, 'foo', 'bar');
|
||||||
|
|
||||||
var inj = injector([NeedsAttributeNoType], null, false, null, attributes);
|
var inj = injector(
|
||||||
|
ListWrapper.concat([NeedsAttributeNoType], extraBindings), null, false, null, attributes);
|
||||||
var needsAttribute = inj.get(NeedsAttributeNoType);
|
var needsAttribute = inj.get(NeedsAttributeNoType);
|
||||||
|
|
||||||
expect(needsAttribute.fooAttribute).toEqual('bar');
|
expect(needsAttribute.fooAttribute).toEqual('bar');
|
||||||
|
@ -830,41 +909,44 @@ export function main() {
|
||||||
|
|
||||||
describe("refs", () => {
|
describe("refs", () => {
|
||||||
it("should inject ElementRef", () => {
|
it("should inject ElementRef", () => {
|
||||||
var inj = injector([NeedsElementRef]);
|
var inj = injector(ListWrapper.concat([NeedsElementRef], extraBindings));
|
||||||
expect(inj.get(NeedsElementRef).elementRef).toBeAnInstanceOf(ElementRef);
|
expect(inj.get(NeedsElementRef).elementRef).toBeAnInstanceOf(ElementRef);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should inject ChangeDetectorRef', function () {
|
it('should inject ChangeDetectorRef', () => {
|
||||||
var cd = new DynamicChangeDetector(null, null, null, [], []);
|
var cd = new DynamicChangeDetector(null, null, null, [], []);
|
||||||
var view = new DummyView();
|
var view = new DummyView();
|
||||||
var childView = new DummyView();
|
var childView = new DummyView();
|
||||||
childView.changeDetector = cd;
|
childView.changeDetector = cd;
|
||||||
view.componentChildViews = [childView];
|
view.componentChildViews = [childView];
|
||||||
var inj = injector([NeedsChangeDetectorRef], null, false, new PreBuiltObjects(null, view, null));
|
var inj = injector(ListWrapper.concat([NeedsChangeDetectorRef], extraBindings),
|
||||||
|
null, false, new PreBuiltObjects(null, view, null));
|
||||||
|
|
||||||
expect(inj.get(NeedsChangeDetectorRef).changeDetectorRef).toBe(cd.ref);
|
expect(inj.get(NeedsChangeDetectorRef).changeDetectorRef).toBe(cd.ref);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should inject ViewContainerRef', () => {
|
it('should inject ViewContainerRef', () => {
|
||||||
var inj = injector([NeedsViewContainer]);
|
var inj = injector(ListWrapper.concat([NeedsViewContainer], extraBindings));
|
||||||
expect(inj.get(NeedsViewContainer).viewContainer).toBeAnInstanceOf(ViewContainerRef);
|
expect(inj.get(NeedsViewContainer).viewContainer).toBeAnInstanceOf(ViewContainerRef);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should inject ProtoViewRef", function () {
|
it("should inject ProtoViewRef", () => {
|
||||||
var protoView = new AppProtoView(null, null, null);
|
var protoView = new AppProtoView(null, null, null);
|
||||||
var inj = injector([NeedsProtoViewRef], null, false, new PreBuiltObjects(null, null, protoView));
|
var inj = injector(ListWrapper.concat([NeedsProtoViewRef], extraBindings),
|
||||||
|
null, false, new PreBuiltObjects(null, null, protoView));
|
||||||
|
|
||||||
expect(inj.get(NeedsProtoViewRef).protoViewRef).toEqual(new ProtoViewRef(protoView));
|
expect(inj.get(NeedsProtoViewRef).protoViewRef).toEqual(new ProtoViewRef(protoView));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should throw if there is no ProtoViewRef", function () {
|
it("should throw if there is no ProtoViewRef", () => {
|
||||||
expect(
|
expect(
|
||||||
() => injector([NeedsProtoViewRef])
|
() => injector(ListWrapper.concat([NeedsProtoViewRef], extraBindings))
|
||||||
).toThrowError('No provider for ProtoViewRef! (NeedsProtoViewRef -> ProtoViewRef)');
|
).toThrowError('No provider for ProtoViewRef! (NeedsProtoViewRef -> ProtoViewRef)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should inject null if there is no ProtoViewRef when the dependency is optional', () => {
|
it('should inject null if there is no ProtoViewRef when the dependency is optional', () => {
|
||||||
var inj = injector([OptionallyInjectsProtoViewRef]);
|
var inj = injector(
|
||||||
|
ListWrapper.concat([OptionallyInjectsProtoViewRef], extraBindings));
|
||||||
var instance = inj.get(OptionallyInjectsProtoViewRef);
|
var instance = inj.get(OptionallyInjectsProtoViewRef);
|
||||||
expect(instance.protoViewRef).toBeNull();
|
expect(instance.protoViewRef).toBeNull();
|
||||||
});
|
});
|
||||||
|
@ -886,12 +968,14 @@ export function main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
it('should be injectable', () => {
|
it('should be injectable', () => {
|
||||||
var inj = injector([NeedsQuery], null, false, preBuildObjects);
|
var inj = injector(ListWrapper.concat([NeedsQuery], extraBindings),
|
||||||
|
null, false, preBuildObjects);
|
||||||
expect(inj.get(NeedsQuery).query).toBeAnInstanceOf(QueryList);
|
expect(inj.get(NeedsQuery).query).toBeAnInstanceOf(QueryList);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should contain directives on the same injector', () => {
|
it('should contain directives on the same injector', () => {
|
||||||
var inj = injector([NeedsQuery, CountingDirective], null, false, preBuildObjects);
|
var inj = injector(ListWrapper.concat([NeedsQuery, CountingDirective], extraBindings),
|
||||||
|
null, false, preBuildObjects);
|
||||||
|
|
||||||
expectDirectives(inj.get(NeedsQuery).query, CountingDirective, [0]);
|
expectDirectives(inj.get(NeedsQuery).query, CountingDirective, [0]);
|
||||||
});
|
});
|
||||||
|
@ -908,7 +992,8 @@ export function main() {
|
||||||
|
|
||||||
it('should contain directives on the same and a child injector in construction order', () => {
|
it('should contain directives on the same and a child injector in construction order', () => {
|
||||||
var protoParent = createPei(null, 0, [NeedsQuery, CountingDirective]);
|
var protoParent = createPei(null, 0, [NeedsQuery, CountingDirective]);
|
||||||
var protoChild = createPei(protoParent, 1, [CountingDirective]);
|
var protoChild = createPei(
|
||||||
|
protoParent, 1, ListWrapper.concat([CountingDirective], extraBindings));
|
||||||
|
|
||||||
var parent = protoParent.instantiate(null);
|
var parent = protoParent.instantiate(null);
|
||||||
var child = protoChild.instantiate(parent);
|
var child = protoChild.instantiate(parent);
|
||||||
|
@ -920,7 +1005,8 @@ export function main() {
|
||||||
|
|
||||||
it('should reflect unlinking an injector', () => {
|
it('should reflect unlinking an injector', () => {
|
||||||
var protoParent = createPei(null, 0, [NeedsQuery, CountingDirective]);
|
var protoParent = createPei(null, 0, [NeedsQuery, CountingDirective]);
|
||||||
var protoChild = createPei(protoParent, 1, [CountingDirective]);
|
var protoChild = createPei(protoParent, 1,
|
||||||
|
ListWrapper.concat([CountingDirective], extraBindings));
|
||||||
|
|
||||||
var parent = protoParent.instantiate(null);
|
var parent = protoParent.instantiate(null);
|
||||||
var child = protoChild.instantiate(parent);
|
var child = protoChild.instantiate(parent);
|
||||||
|
@ -935,7 +1021,8 @@ export function main() {
|
||||||
it('should reflect moving an injector as a last child', () => {
|
it('should reflect moving an injector as a last child', () => {
|
||||||
var protoParent = createPei(null, 0, [NeedsQuery, CountingDirective]);
|
var protoParent = createPei(null, 0, [NeedsQuery, CountingDirective]);
|
||||||
var protoChild1 = createPei(protoParent, 1, [CountingDirective]);
|
var protoChild1 = createPei(protoParent, 1, [CountingDirective]);
|
||||||
var protoChild2 = createPei(protoParent, 1, [CountingDirective]);
|
var protoChild2 = createPei(protoParent, 1,
|
||||||
|
ListWrapper.concat([CountingDirective], extraBindings));
|
||||||
|
|
||||||
var parent = protoParent.instantiate(null);
|
var parent = protoParent.instantiate(null);
|
||||||
var child1 = protoChild1.instantiate(parent);
|
var child1 = protoChild1.instantiate(parent);
|
||||||
|
@ -955,7 +1042,8 @@ export function main() {
|
||||||
it('should reflect moving an injector as a first child', () => {
|
it('should reflect moving an injector as a first child', () => {
|
||||||
var protoParent = createPei(null, 0, [NeedsQuery, CountingDirective]);
|
var protoParent = createPei(null, 0, [NeedsQuery, CountingDirective]);
|
||||||
var protoChild1 = createPei(protoParent, 1, [CountingDirective]);
|
var protoChild1 = createPei(protoParent, 1, [CountingDirective]);
|
||||||
var protoChild2 = createPei(protoParent, 1, [CountingDirective]);
|
var protoChild2 = createPei(protoParent, 1,
|
||||||
|
ListWrapper.concat([CountingDirective], extraBindings));
|
||||||
|
|
||||||
var parent = protoParent.instantiate(null);
|
var parent = protoParent.instantiate(null);
|
||||||
var child1 = protoChild1.instantiate(parent);
|
var child1 = protoChild1.instantiate(parent);
|
||||||
|
@ -975,7 +1063,8 @@ export function main() {
|
||||||
it('should support two concurrent queries for the same directive', () => {
|
it('should support two concurrent queries for the same directive', () => {
|
||||||
var protoGrandParent = createPei(null, 0, [NeedsQuery]);
|
var protoGrandParent = createPei(null, 0, [NeedsQuery]);
|
||||||
var protoParent = createPei(null, 0, [NeedsQuery]);
|
var protoParent = createPei(null, 0, [NeedsQuery]);
|
||||||
var protoChild = createPei(protoParent, 1, [CountingDirective]);
|
var protoChild = createPei(protoParent, 1,
|
||||||
|
ListWrapper.concat([CountingDirective], extraBindings));
|
||||||
|
|
||||||
var grandParent = protoGrandParent.instantiate(null);
|
var grandParent = protoGrandParent.instantiate(null);
|
||||||
var parent = protoParent.instantiate(grandParent);
|
var parent = protoParent.instantiate(grandParent);
|
||||||
|
@ -997,6 +1086,9 @@ export function main() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class ContextWithHandler {
|
class ContextWithHandler {
|
||||||
|
|
Loading…
Reference in New Issue