reactant-di
Version:
A dependency injection lib for Reactant
405 lines (329 loc) • 8.46 kB
text/typescript
import { injectable, createContainer, inject, Optional } from '../..';
describe('@injectable', () => {
test('no argument', () => {
@injectable()
class Foo {
public get test() {
return 'test';
}
}
@injectable()
class Bar {
constructor(public foo: Foo) {}
public get test() {
return this.foo.test;
}
}
const bar = createContainer({
ServiceIdentifiers: new Map(),
}).get(Bar);
expect(bar.test).toBe('test');
});
test('no argument with metadata identifier', () => {
@injectable()
class Foo {
public get test() {
return 'test';
}
}
@injectable()
class Bar {
constructor(@inject(Foo) public foo: Foo) {}
public get test() {
return this.foo.test;
}
}
const bar = createContainer({
ServiceIdentifiers: new Map(),
}).get(Bar);
expect(bar.test).toBe('test');
});
test('no decorate with implicit identifier', () => {
class Foo {
public get test() {
return 'test';
}
}
class Bar {
constructor(@inject() public foo: Foo) {}
public get test() {
return this.foo.test;
}
}
const bar = createContainer({
ServiceIdentifiers: new Map(),
modules: [Bar, Foo],
}).get(Bar);
expect(bar.test).toBe('test');
});
test('mix - no decorate and implicit identifier', () => {
@injectable()
class Foo {
public get test() {
return 'test';
}
}
class Bar {
constructor(@inject(Foo) public foo: Foo) {}
public get test() {
return this.foo.test;
}
}
const bar = createContainer({
ServiceIdentifiers: new Map(),
modules: [Bar, Foo],
}).get(Bar);
expect(bar.test).toBe('test');
});
test('mix - with argument and without metadata mode', () => {
@injectable()
class Foo {}
@injectable()
class FooBar {}
@injectable({
deps: [{ provide: 'Foo', optional: true }],
})
class Bar {
public foo: Foo;
constructor(foo: any, public fooBar: FooBar) {
this.foo = foo;
}
}
const bar = createContainer({
ServiceIdentifiers: new Map(),
modules: [Bar, { provide: 'Foo', useClass: Foo }],
}).get(Bar);
expect(bar.foo instanceof Foo).toBeTruthy();
expect(bar.fooBar instanceof FooBar).toBeTruthy();
});
test('injectable error', () => {
@injectable()
class Foo {}
for (const item of [
{ provide1: 'OptionalFoos', multi: true, optional: true },
'',
undefined,
null,
true,
false,
0,
{},
[],
]) {
expect(() => {
@injectable({
deps: [
// @ts-ignore
item,
],
})
class Bar {
public optionalFoos: Foo[];
constructor(optionalFoos: any[]) {
this.optionalFoos = optionalFoos;
}
}
const bar = createContainer({
ServiceIdentifiers: new Map(),
modules: [],
}).get(Bar);
}).toThrowError(/option error/);
}
});
test('multi-deps', () => {
@injectable()
class Foo {}
@injectable()
class Foo0 {}
@injectable()
class Foo1 {}
@injectable()
class Foo2 {}
@injectable()
class Foo3 {}
@injectable()
class Foo4 {}
@injectable({
deps: [
Foo,
{ provide: Foo0 },
{ provide: 'Foo1' },
{ provide: 'Foo2', optional: true },
{ provide: 'Foos', multi: true },
{ provide: 'OptionalFoos', multi: true, optional: true },
],
})
class Bar {
public foo: Foo;
public foo0: Foo0;
public foo1: Foo1;
public foo2: any;
public foos: Foo3[];
public optionalFoos: Foo4[];
constructor(
foo: any,
foo0: any,
foo1: any,
foo2: any,
foos: any[],
optionalFoos: any[]
) {
this.foo = foo;
this.foo0 = foo0;
this.foo1 = foo1;
this.foo2 = foo2;
this.foos = foos;
this.optionalFoos = optionalFoos;
}
}
const bar = createContainer({
ServiceIdentifiers: new Map(),
modules: [
{ provide: 'Foo1', useClass: Foo1 },
{ provide: 'Foos', useClass: Foo3 },
],
}).get(Bar);
expect(bar instanceof Bar).toBeTruthy();
expect(bar.foo instanceof Foo).toBeTruthy();
expect(bar.foo0 instanceof Foo0).toBeTruthy();
expect(bar.foo1 instanceof Foo1).toBeTruthy();
expect(bar.foo2).toBeUndefined();
expect(bar.foos[0] instanceof Foo3).toBeTruthy();
expect(bar.optionalFoos).toEqual([]);
});
test('multi-deps with optional', () => {
@injectable()
class Foo {}
@injectable()
class Foo0 {}
@injectable()
class Foo1 {}
@injectable()
class Foo2 {}
@injectable()
class Foo3 {}
@injectable()
class Foo4 {}
@injectable({
deps: [
Foo,
{ provide: Foo0 },
{ provide: 'Foo1' },
{ provide: 'Foo2', optional: true },
{ provide: 'Foos', multi: true },
{ provide: 'OptionalFoos', multi: true, optional: true },
],
})
class Bar {
public foo: Foo;
public foo0: Foo0;
public foo1: Foo1;
public foo2: any;
public foos: Foo3[];
public optionalFoos: Foo4[];
constructor(
foo: any,
foo0: any,
foo1: any,
foo2: any,
foos: any[],
optionalFoos: any[]
) {
this.foo = foo;
this.foo0 = foo0;
this.foo1 = foo1;
this.foo2 = foo2;
this.foos = foos;
this.optionalFoos = optionalFoos;
}
}
const bar = createContainer({
ServiceIdentifiers: new Map(),
modules: [
{ provide: 'Foo1', useClass: Foo1 },
{ provide: 'Foo2', useClass: Foo2 },
{ provide: 'Foos', useClass: Foo3 },
{ provide: 'OptionalFoos', useClass: Foo4 },
],
}).get(Bar);
expect(bar instanceof Bar).toBeTruthy();
expect(bar.foo instanceof Foo).toBeTruthy();
expect(bar.foo0 instanceof Foo0).toBeTruthy();
expect(bar.foo1 instanceof Foo1).toBeTruthy();
expect(bar.foo2 instanceof Foo2).toBeTruthy();
expect(bar.foos[0] instanceof Foo3).toBeTruthy();
expect(bar.optionalFoos[0] instanceof Foo4).toBeTruthy();
});
test('mix - resolve optional and require ', () => {
@injectable()
class Foo {}
@injectable({
deps: [{ provide: Foo, optional: true }],
})
class Bar {
constructor(public foo: any) {}
}
@injectable({
deps: [{ provide: Foo, optional: true }],
})
class Bar1 {
constructor(public foo: any) {}
}
@injectable({
deps: [Bar, Bar1, Foo],
})
class FooBar {
constructor(public bar: any, public bar1: any, public foo: any) {}
}
const fooBar = createContainer({
ServiceIdentifiers: new Map(),
modules: [{ provide: Bar, deps: [new Optional(Foo)] }],
}).get(FooBar);
expect(fooBar.bar.foo).toBeUndefined();
expect(fooBar.foo instanceof Foo).toBeTruthy();
expect(fooBar.bar1 instanceof Bar1).toBeTruthy();
});
test('string identifier for changing deps other module with config', () => {
@injectable()
class Foo {}
@injectable()
class Foo0 {}
@injectable({
deps: [{ provide: 'foo' }],
})
class Bar {
constructor(public foo: any) {}
}
@injectable({
deps: [{ provide: 'bar' }],
})
class FooBar {
constructor(public bar: any) {}
}
const fooBar = createContainer({
ServiceIdentifiers: new Map(),
modules: [
{ provide: 'bar', useClass: Bar, deps: ['foo1'] },
{ provide: 'foo1', useClass: Foo0 },
],
}).get(FooBar);
expect(fooBar.bar.foo instanceof Foo0).toBeTruthy();
});
test('without metadata mode for changing deps other module with config', () => {
@injectable()
class Foo {}
@injectable()
class Foo0 {}
@injectable({
deps: [Foo],
})
class Bar {
constructor(public foo: any) {}
}
const bar = createContainer({
ServiceIdentifiers: new Map(),
modules: [{ provide: Bar, useClass: Bar, deps: [Foo0] }],
}).get(Bar);
expect(bar.foo instanceof Foo0).toBeTruthy();
});
});