Skip to content

Commit

Permalink
feat: Handle async loading for config and run hooks modules (#55)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: The bootstrap method returns a promise.
Co-authored-by: Florian Belliard <[email protected]>
  • Loading branch information
jerome-quere authored Mar 26, 2020
1 parent 1942b83 commit 3ca6246
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 68 deletions.
23 changes: 15 additions & 8 deletions src/Module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export class Module {
* Bootstrap the module
* @return The module injector
*/
bootstrap(): Injector {
async bootstrap(): Promise<Injector> {
const modules: Module[] = []
const $injectors: Injector[] = []

Expand All @@ -134,14 +134,21 @@ export class Module {
$injectors.push($injector)

// TODO maybe throw if a service instance try to be injected in the config hook
modules.forEach((module, i) => {
module.configHooks.forEach(hook => $injectors[i].invoke(hook))
})

modules.forEach((module, i) => {
module.runHooks.forEach(hook => $injectors[i].invoke(hook))
})
for (let i = 0; modules.length > i; i++) {
let module = modules[i]
for (let j = 0; module.configHooks.length > j; j++) {
let hook = module.configHooks[j]
await $injectors[i].invoke(hook)
}
}

for (let i = 0; modules.length > i; i++) {
let module = modules[i]
for (let j = 0; module.runHooks.length > j; j++) {
let hook = module.runHooks[j]
await $injectors[i].invoke(hook)
}
}
return $injector
}

Expand Down
53 changes: 27 additions & 26 deletions test/injector.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,26 @@ import { radis, Injector } from '../src'
/* tslint:disable:no-empty */

describe('Injector', function() {
it('the injector should be injected at runtine', () => {
radis
it('the injector should be injected at runtine', async () => {
await radis
.module('module', [])
.run($injector => {
expect($injector).toBeInstanceOf(Injector)
})
.bootstrap()
})

it('the injector should be injected at config time', () => {
radis
it('the injector should be injected at config time', async () => {
await radis
.module('module', [])
.config($injector => {
expect($injector).toBeInstanceOf(Injector)
})
.bootstrap()
})

it('The injector should parse all kind of function declaration', () => {
radis
it('The injector should parse all kind of function declaration', async () => {
await radis
.module('module', [])
.factory('s1', () => 's1')
.factory('s2', () => 's2')
Expand Down Expand Up @@ -52,23 +52,23 @@ describe('Injector', function() {
.bootstrap()
})

it('Should throw on invalid function', () => {
it('Should throw on invalid function', async () => {
const test: any = function(a) {}
const _toString = Function.prototype.toString
Function.prototype.toString = () => 'a =\\> =\\> function (){}'
expect(() => {
await expect(
radis
.module('module', [])
.run(test)
.bootstrap()
}).toThrow()
).rejects.toThrow(Error)
Function.prototype.toString = _toString
})

it('Should work with no parentesis arrow function', () => {
it('Should work with no parentesis arrow function', async () => {
const test: any = function(s1) {}
const _toString = Function.prototype.toString
const $injector = radis
const $injector = await radis
.module('module', [])
.factory('s1', () => 's1')
.run(s1 => {})
Expand All @@ -90,32 +90,32 @@ describe('Injector', function() {
.factory('s2', () => 's2')
})

it('Should return the right service', () => {
module
it('Should return the right service', async () => {
await module
.run($injector => {
expect($injector.getService('s1')).toBe('s1')
expect($injector.getService('s2')).toBe('s2')
})
.bootstrap()
})

it('Should throw if service does not exist', () => {
module
it('Should throw if service does not exist', async () => {
await module
.run($injector => {
expect(() => $injector.getService('s3')).toThrow(Error)
})
.bootstrap()
})

it('Should get provider', () => {
module
it('Should get provider', async () => {
await module
.run($injector => {
expect($injector.getService('s1Provider')).toBeTruthy()
})
.bootstrap()
})
it('Should throw when provider do not exist', () => {
module
it('Should throw when provider do not exist', async () => {
await module
.run($injector => {
expect(() => $injector.getService('s3Provider')).toThrow()
})
Expand All @@ -142,8 +142,8 @@ describe('Injector', function() {
}
}

beforeEach(() => {
$injector = radis
beforeEach(async () => {
$injector = await radis
.module('module', [])
.factory('s1', () => 10)
.factory('s2', () => 20)
Expand Down Expand Up @@ -207,7 +207,7 @@ describe('Injector', function() {
})

describe('#instantiate', () => {
it('Should inject services', () => {
it('Should inject services', async () => {
class Service {
static get $inject() {
return ['s1']
Expand All @@ -217,11 +217,12 @@ describe('Injector', function() {
}
}

radis
const $injector = await radis
.module('module')
.factory('s1', () => 's1')
.bootstrap()
.instantiate(Service)

$injector.instantiate(Service)
})
})

Expand All @@ -241,8 +242,8 @@ describe('Injector', function() {
}
}

beforeEach(() => {
$injector = radis
beforeEach(async () => {
$injector = await radis
.module('module', [])
.factory('s1', () => 's1')
.factory('s2', () => 's2')
Expand Down
24 changes: 12 additions & 12 deletions test/module-dependencies.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import radis from '../src'

describe('ModuleDependencies', () => {
describe('Simple dependency', () => {
it('should get the dependency service', () => {
it('should get the dependency service', async () => {
const m1 = radis.module('m1', []).factory('s1', () => 's1')
const m2 = radis.module('m2', [m1]).factory('s2', () => 's2')
const m3 = radis.module('m3', [m2]).factory('s3', () => 's3')
Expand All @@ -18,10 +18,10 @@ describe('ModuleDependencies', () => {
expect(s3).toBe('s3')
})

m3.bootstrap()
await m3.bootstrap()
})

it('should override the child dependency', () => {
it('should override the child dependency', async () => {
const m1 = radis.module('m1', []).factory('service', () => 's1')
const m2 = radis.module('m2', [m1]).factory('service', () => 's2')
const m3 = radis.module('m3', [m2, m1]).factory('service', () => 's3')
Expand All @@ -30,19 +30,19 @@ describe('ModuleDependencies', () => {
m2.run(service => expect(service).toBe('s2'))
m3.run(service => expect(service).toBe('s3'))

m3.bootstrap()
await m3.bootstrap()
})

it('should get the closest child dependency', () => {
it('should get the closest child dependency', async () => {
const m1 = radis.module('m1', []).factory('service', () => 's1')
const m2 = radis.module('m2', [m1]).factory('service', () => 's2')
const m3 = radis.module('m3', [m2])

m3.run(service => expect(service).toBe('s2'))
m3.bootstrap()
await m3.bootstrap()
})

it('should call dependency first', () => {
it('should call dependency first', async () => {
const m1 = radis.module('m1', []).factory('s1', () => 's1')
const m2 = radis.module('m2', [m1]).factory('s2', () => 's2')

Expand All @@ -54,10 +54,10 @@ describe('ModuleDependencies', () => {
m2.config(s2Provider => expect(count++).toBe(1))
m2.run(s2 => expect(count++).toBe(3))

m2.bootstrap()
await m2.bootstrap()
})

it('should get a shared instance', () => {
it('should get a shared instance', async () => {
const m1 = radis.module('m1').factory('s', () => ({ v: 0 }))
const m2 = radis.module('m2', [m1])
const m3 = radis.module('m2', [m1])
Expand All @@ -68,10 +68,10 @@ describe('ModuleDependencies', () => {
m3.run(s => expect(s.v++).toBe(2))
m4.run(s => expect(s.v++).toBe(3))

m4.bootstrap()
await m4.bootstrap()
})

it('should be call in the right order', () => {
it('should be call in the right order', async () => {
let count = 0

const m1 = radis.module('m1').factory('s', () => {
Expand All @@ -92,7 +92,7 @@ describe('ModuleDependencies', () => {
m3.run(s => expect(count++).toBe(7))
m4.run(s => expect(count++).toBe(8))

m4.bootstrap()
await m4.bootstrap()
})
})
})
Loading

0 comments on commit 3ca6246

Please sign in to comment.