@difizen/mana-syringe
Version:
292 lines (288 loc) • 9.81 kB
text/typescript
import assert from 'assert';
import { register, GlobalContainer, Container } from './container';
import { Syringe } from './core';
import { singleton, transient, injectable } from './decorator';
import { Module } from './module';
describe('container', () => {
describe('default', () => {
it('#injectable register', () => {
class Injectable {}
register(Injectable);
const foo = GlobalContainer.get(Injectable);
assert(foo instanceof Injectable);
});
it('#injectable child container', () => {
const child = GlobalContainer.createChild();
assert(child.parent === GlobalContainer);
});
it('#singleton register & event', () => {
const container = GlobalContainer.createChild();
let registered = false;
container.onRegistered(() => {
registered = true;
});
class Singleton {}
container.register(Singleton);
const foo1 = container.get(Singleton);
const foo2 = container.get(Singleton);
assert(foo1 === foo2);
assert(registered);
});
it('#transient register', () => {
class Transient {}
register(Transient, {});
const foo1 = GlobalContainer.get(Transient);
const foo2 = GlobalContainer.get(Transient);
assert(foo1 !== foo2);
});
it('#option register', () => {
class Injectable {}
register({ token: Injectable, useClass: Injectable });
const foo = GlobalContainer.get(Injectable);
assert(foo instanceof Injectable);
});
it('#isBound', () => {
class Injectable {}
register({ token: Injectable, useClass: Injectable });
assert(GlobalContainer.isBound(Injectable));
});
it('#rebind', () => {
class InjectableFoo {}
register(InjectableFoo);
assert(GlobalContainer.isBound(InjectableFoo));
const childContainer = GlobalContainer.createChild();
class InjectableFoo1 extends InjectableFoo {}
childContainer.register({ token: InjectableFoo, useClass: InjectableFoo1 });
const instance = childContainer.get(InjectableFoo);
assert(instance instanceof InjectableFoo1);
});
it('#token', () => {
const TokenSymbol = Symbol('TokenSymbol');
class Token {}
register(Token);
const foo1 = GlobalContainer.get(Token);
const foo2 = GlobalContainer.get(TokenSymbol);
assert(foo1 !== foo2);
});
it('#named token', () => {
const TokenSymbol = Symbol('TokenSymbol');
const named = 'named';
class Token {}
register(Token);
const foo1 = GlobalContainer.getNamed(TokenSymbol, named);
const foo2 = GlobalContainer.get(Token);
assert(foo1 !== foo2);
});
it('#named tokens', () => {
const TokenSymbol = Symbol('TokenSymbol');
const named = 'named';
class Token {}
register(Token);
const foo1 = GlobalContainer.getNamed(TokenSymbol, named);
const fooArray = GlobalContainer.getAllNamed(TokenSymbol, named);
assert(fooArray.includes(foo1));
});
it('#array token', () => {
const FooSymbol = Symbol('FooSymbol');
const BarSymbol = Symbol('BarSymbol');
class ArrayToken {}
register(ArrayToken);
const foo1 = GlobalContainer.get(ArrayToken);
const foo2 = GlobalContainer.get(FooSymbol);
const foo3 = GlobalContainer.get(BarSymbol);
assert(foo1 !== foo2);
assert(foo1 !== foo3);
assert(foo3 !== foo2);
});
it('#undefined value', () => {
const TokenSymbol = Symbol('UndefinedToken');
register({ token: TokenSymbol, useValue: undefined });
const foo1 = GlobalContainer.get(TokenSymbol);
assert(typeof foo1 === 'undefined');
});
it('#get all', () => {
const token = Syringe.defineToken('token');
class Foo {}
class Bar {}
register(token, { useClass: [Foo, Bar] });
const list = GlobalContainer.getAll(token);
assert(list instanceof Array);
assert(list.length === 2);
});
it('#get from parent', () => {
const token = Syringe.defineToken('token');
class Foo {}
const childContainer = GlobalContainer.createChild();
class Bar {}
register(token, { useClass: Foo });
childContainer.register(token, { useClass: Bar });
const list = GlobalContainer.getAll(token);
assert(list instanceof Array);
assert(list.length === 1);
});
it('#mono token', () => {
class Foo {}
class Bar {}
register(Bar, { useClass: [Foo] });
const foo1 = GlobalContainer.get(Bar);
assert(foo1 instanceof Foo);
});
it('#contrib', () => {
const FooSymbol = Symbol('FooSymbol');
class Contrib {}
register(Contrib);
const foo1 = GlobalContainer.get(Contrib);
const foo2 = GlobalContainer.get(FooSymbol);
assert(foo1 === foo2);
});
it('#contrib with transient', () => {
const FooSymbol = Symbol('FooSymbol');
class ContribTransient {}
register(ContribTransient);
const foo1 = GlobalContainer.get(ContribTransient);
const foo2 = GlobalContainer.get(FooSymbol);
assert(foo1 === foo2);
});
it('#array contrib', () => {
const FooSymbol = Symbol('FooSymbol');
const BarSymbol = Symbol('BarSymbol');
class ArrayContrib {}
register(ArrayContrib);
const foo1 = GlobalContainer.get(ArrayContrib);
const foo2 = GlobalContainer.get(FooSymbol);
assert(foo1 === foo2);
});
it('#contrib to mono/multi token', () => {
const FooSymbol = Symbol('FooSymbol');
const BarSymbol = Syringe.defineToken('BarSymbol');
register({ token: FooSymbol, useValue: FooSymbol });
register({ token: BarSymbol, useValue: undefined });
class FooContribToMonoMulti {}
register(FooContribToMonoMulti);
const obj = GlobalContainer.get(FooContribToMonoMulti);
const objFoo = GlobalContainer.get(FooSymbol);
const barList = GlobalContainer.getAll(BarSymbol);
assert(obj === objFoo);
assert(barList.includes(objFoo));
assert(barList.includes(undefined));
assert(barList.length === 2);
});
it('#remove', () => {
class Foo {}
try {
register(Foo);
GlobalContainer.remove(Foo);
GlobalContainer.get(Foo);
assert(false);
} catch (ex) {
assert(true);
}
});
it('#remove contrib', () => {
const FooSymbol = Syringe.defineToken('FooSymbol');
class FooContribution {}
class BarContribution {}
register(FooContribution);
register(BarContribution);
const contribs = GlobalContainer.getAll(FooSymbol);
assert(contribs.length === 2);
assert(contribs[0] instanceof FooContribution);
GlobalContainer.remove(FooSymbol);
assert(!GlobalContainer.isBound(FooSymbol));
register(FooContribution);
const emptyContribs = GlobalContainer.getAll(FooSymbol);
assert(emptyContribs.length === 1);
});
it('#load module and event', () => {
const container = GlobalContainer.createChild();
let loaded = false;
container.onModuleChanged(() => {
loaded = true;
});
class Foo {}
const baseModule = Module().register(Foo);
container.load(baseModule);
assert(loaded);
assert(container.isBound(Foo));
});
});
describe('basic', () => {
it('#new container', () => {
class NewContainer {}
const container = new Container();
container.register(NewContainer);
const foo = container.get(NewContainer);
assert(foo instanceof NewContainer);
});
it('#global config', () => {
Container.config({ lifecycle: Syringe.Lifecycle.singleton });
class GlobalConfig {}
register(GlobalConfig);
const foo1 = GlobalContainer.get(GlobalConfig);
const foo2 = GlobalContainer.get(GlobalConfig);
assert(foo1 === foo2);
});
it('#global config downgrade', () => {
Container.config({});
class GlobalConfigDown {}
register(GlobalConfigDown);
const foo1 = GlobalContainer.get(GlobalConfigDown);
const foo2 = GlobalContainer.get(GlobalConfigDown);
assert(foo1 !== foo2);
});
it('#invalid register', () => {
const InvalidSymbol = Symbol('InvalidSymbol');
register(InvalidSymbol);
let flag = true;
try {
GlobalContainer.get(InvalidSymbol);
} catch (ex) {
flag = false;
}
assert(!flag);
});
it('#invalid register empty', () => {
const InvalidSymbol = Symbol('InvalidSymbol');
register(InvalidSymbol);
let flag = true;
try {
GlobalContainer.get(InvalidSymbol);
} catch (ex) {
flag = false;
}
assert(!flag);
});
it('#container context', () => {
const context = GlobalContainer.get(Syringe.ContextToken);
assert(context.container === GlobalContainer);
});
});
});