Repository: artusjs/core
Pull request #166 (2022-08-10 06:19:13)

fix: should await lifecycle configdidload

- [x] `npm test` passes
- [x] tests and/or benchmarks are included
- [ ] documentation is changed or added
- [x] commit message follows commit guidelines


##### Description of change
<!-- Provide a description of the change below this comment. -->

- configdidload 需要 return ，不然 configdidload 异步的话，执行顺序会有问题
- 补充 lifecycle 的单测文件

codecov-commenter: # [Codecov](https://codecov.io/gh/artusjs/core/pull/166?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) Report
> Merging [#166](https://codecov.io/gh/artusjs/core/pull/166?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) (90bc33b) into [master](https://codecov.io/gh/artusjs/core/commit/f2a7142a80fa69bedf4e6db178bc7cea95b83e51?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) (f2a7142) will **not change** coverage.
> The diff coverage is `100.00%`.

> :exclamation: Current head 90bc33b differs from pull request most recent head 4ada675. Consider uploading reports for the commit 4ada675 to get more accurate results

```diff
@@           Coverage Diff           @@
##           master     #166   +/-   ##
=======================================
  Coverage   89.57%   89.57%           
=======================================
  Files          51       51           
  Lines        1094     1094           
  Branches      180      180           
=======================================
  Hits          980      980           
  Misses        114      114           
```


| [Impacted Files](https://codecov.io/gh/artusjs/core/pull/166?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) | Coverage Δ | |
|---|---|---|
| [src/application.ts](https://codecov.io/gh/artusjs/core/pull/166/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-c3JjL2FwcGxpY2F0aW9uLnRz) | `91.42% <100.00%> (ø)` | |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None)


Patch:
diff --git a/src/application.ts b/src/application.ts
index 6a49384..c85bbad 100644
--- a/src/application.ts
+++ b/src/application.ts
@@ -116,7 +116,7 @@ export class ArtusApplication implements Application {
             id: ArtusInjectEnum.Config,
             value: this.configurationHandler.getAllConfig(),
           });
-          this.lifecycleManager.emitHook('configDidLoad');
+          return this.lifecycleManager.emitHook('configDidLoad');
         },
       })
       .addLoaderListener('framework-config', {


Test patch:
diff --git a/test/fixtures/app_with_lifecycle/bootstrap.ts b/test/fixtures/app_with_lifecycle/bootstrap.ts
new file mode 100644
index 0000000..97aad97
--- /dev/null
+++ b/test/fixtures/app_with_lifecycle/bootstrap.ts
@@ -0,0 +1,57 @@
+import {
+  ArtusApplication,
+  ApplicationLifecycle, LifecycleHookUnit, LifecycleHook, ArtusInjectEnum,
+} from '../../../src/index';
+
+import { Container, Inject } from '@artus/injection';
+import LifecycleList from './lifecyclelist';
+export const TEST_LIFE_CYCLE_LIST = 'TEST_LIFE_CYCLE_LIST';
+
+@LifecycleHookUnit()
+export default class AppLifecycle implements ApplicationLifecycle {
+  @Inject(ArtusInjectEnum.Application)
+  app: ArtusApplication;
+
+  @Inject()
+  container: Container;
+
+  @Inject()
+  lifecycleList: LifecycleList;
+
+  @LifecycleHook()
+  async configWillLoad() {
+    this.container.set({ id: TEST_LIFE_CYCLE_LIST, value: this.lifecycleList });
+    await new Promise(resolve => setTimeout(resolve, 100));
+    this.lifecycleList.add('app_configWillLoad');
+  }
+
+  @LifecycleHook('configDidLoad')
+  async customNameConfigDidLoad() {
+    await new Promise(resolve => setTimeout(resolve, 100));
+    this.lifecycleList.add('app_configDidLoad');
+  }
+
+  @LifecycleHook('didLoad')
+  async  didLoad() {
+    await new Promise(resolve => setTimeout(resolve, 100));
+    this.lifecycleList.add('app_didLoad');
+  }
+
+  @LifecycleHook('willReady')
+  async willReady() {
+    await new Promise(resolve => setTimeout(resolve, 100));
+    this.lifecycleList.add('app_willReady');
+  }
+
+  @LifecycleHook('didReady')
+  async didReady() {
+    await new Promise(resolve => setTimeout(resolve, 100));
+    this.lifecycleList.add('app_didReady');
+  }
+
+  @LifecycleHook()
+  async beforeClose() {
+    await new Promise(resolve => setTimeout(resolve, 100));
+    this.lifecycleList.add('app_beforeClose');
+  }
+}
diff --git a/test/fixtures/app_with_lifecycle/config/config.default.ts b/test/fixtures/app_with_lifecycle/config/config.default.ts
new file mode 100644
index 0000000..7c645e4
--- /dev/null
+++ b/test/fixtures/app_with_lifecycle/config/config.default.ts
@@ -0,0 +1,1 @@
+export default {};
\ No newline at end of file
diff --git a/test/fixtures/app_with_lifecycle/config/plugin.ts b/test/fixtures/app_with_lifecycle/config/plugin.ts
new file mode 100644
index 0000000..7bb4ac3
--- /dev/null
+++ b/test/fixtures/app_with_lifecycle/config/plugin.ts
@@ -0,0 +1,13 @@
+import path from 'path';
+
+export default {
+  pluginA: {
+    enable: true,
+    path: path.resolve(__dirname, '../plugins/plugin-a'),
+  },
+
+  pluginB: {
+    enable: true,
+    path: path.resolve(__dirname, '../plugins/plugin-b'),
+  },
+};
diff --git a/test/fixtures/app_with_lifecycle/lifecyclelist.ts b/test/fixtures/app_with_lifecycle/lifecyclelist.ts
new file mode 100644
index 0000000..4eb2e18
--- /dev/null
+++ b/test/fixtures/app_with_lifecycle/lifecyclelist.ts
@@ -0,0 +1,10 @@
+import { Injectable } from '../../../src';
+
+@Injectable()
+export default class LifecycleList {
+  lifecycleList: string[] = [];
+
+  async add(name: string) {
+    this.lifecycleList.push(name);
+  }
+}
diff --git a/test/fixtures/app_with_lifecycle/plugins/plugin-a/bootstrap.ts b/test/fixtures/app_with_lifecycle/plugins/plugin-a/bootstrap.ts
new file mode 100644
index 0000000..c52f7e6
--- /dev/null
+++ b/test/fixtures/app_with_lifecycle/plugins/plugin-a/bootstrap.ts
@@ -0,0 +1,55 @@
+import {
+  ArtusApplication,
+  ApplicationLifecycle, LifecycleHookUnit, LifecycleHook, ArtusInjectEnum,
+} from '../../../../../src';
+
+import { Container, Inject } from '@artus/injection';
+import LifecycleList from '../../lifecyclelist';
+
+@LifecycleHookUnit()
+export default class AppLifecycle implements ApplicationLifecycle {
+  @Inject(ArtusInjectEnum.Application)
+  app: ArtusApplication;
+
+  @Inject()
+  container: Container;
+
+  @Inject()
+  lifecycleList: LifecycleList;
+
+  @LifecycleHook()
+  async configWillLoad() {
+    await new Promise(resolve => setTimeout(resolve, 100));
+    this.lifecycleList.add('pluginA_configWillLoad');
+  }
+
+  @LifecycleHook('configDidLoad')
+  async customNameConfigDidLoad() {
+    await new Promise(resolve => setTimeout(resolve, 100));
+    this.lifecycleList.add('pluginA_configDidLoad');
+  }
+
+  @LifecycleHook('didLoad')
+  async  didLoad() {
+    await new Promise(resolve => setTimeout(resolve, 100));
+    this.lifecycleList.add('pluginA_didLoad');
+  }
+
+  @LifecycleHook('willReady')
+  async willReady() {
+    await new Promise(resolve => setTimeout(resolve, 100));
+    this.lifecycleList.add('pluginA_willReady');
+  }
+
+  @LifecycleHook('didReady')
+  async didReady() {
+    await new Promise(resolve => setTimeout(resolve, 100));
+    this.lifecycleList.add('pluginA_didReady');
+  }
+
+  @LifecycleHook()
+  async beforeClose() {
+    await new Promise(resolve => setTimeout(resolve, 100));
+    this.lifecycleList.add('pluginA_beforeClose');
+  }
+}
diff --git a/test/fixtures/app_with_lifecycle/plugins/plugin-a/meta.json b/test/fixtures/app_with_lifecycle/plugins/plugin-a/meta.json
new file mode 100644
index 0000000..8f14b5b
--- /dev/null
+++ b/test/fixtures/app_with_lifecycle/plugins/plugin-a/meta.json
@@ -0,0 +1,3 @@
+{
+  "name": "pluginA"
+}
\ No newline at end of file
diff --git a/test/fixtures/app_with_lifecycle/plugins/plugin-b/bootstrap.ts b/test/fixtures/app_with_lifecycle/plugins/plugin-b/bootstrap.ts
new file mode 100644
index 0000000..4390350
--- /dev/null
+++ b/test/fixtures/app_with_lifecycle/plugins/plugin-b/bootstrap.ts
@@ -0,0 +1,49 @@
+import {
+  ArtusApplication,
+  ApplicationLifecycle, LifecycleHookUnit, LifecycleHook, ArtusInjectEnum,
+} from '../../../../../src';
+
+import { Container, Inject } from '@artus/injection';
+import LifecycleList from '../../lifecyclelist';
+
+@LifecycleHookUnit()
+export default class AppLifecycle implements ApplicationLifecycle {
+  @Inject(ArtusInjectEnum.Application)
+  app: ArtusApplication;
+
+  @Inject()
+  container: Container;
+
+  @Inject()
+  lifecycleList: LifecycleList;
+
+  @LifecycleHook('configWillLoad')
+  customConfigWillLoad() {
+    this.lifecycleList.add('pluginB_configWillLoad');
+  }
+
+  @LifecycleHook('configDidLoad')
+  customNameConfigDidLoad() {
+    this.lifecycleList.add('pluginB_configDidLoad');
+  }
+
+  @LifecycleHook('didLoad')
+  didLoad() {
+    this.lifecycleList.add('pluginB_didLoad');
+  }
+
+  @LifecycleHook('willReady')
+  willReady() {
+    this.lifecycleList.add('pluginB_willReady');
+  }
+
+  @LifecycleHook('didReady')
+  didReady() {
+    this.lifecycleList.add('pluginB_didReady');
+  }
+
+  @LifecycleHook()
+  beforeClose() {
+    this.lifecycleList.add('pluginB_beforeClose');
+  }
+}
diff --git a/test/fixtures/app_with_lifecycle/plugins/plugin-b/meta.json b/test/fixtures/app_with_lifecycle/plugins/plugin-b/meta.json
new file mode 100644
index 0000000..b830e69
--- /dev/null
+++ b/test/fixtures/app_with_lifecycle/plugins/plugin-b/meta.json
@@ -0,0 +1,3 @@
+{
+  "name": "pluginB"
+}
\ No newline at end of file
diff --git a/test/lifecycle.test.ts b/test/lifecycle.test.ts
new file mode 100644
index 0000000..dd64932
--- /dev/null
+++ b/test/lifecycle.test.ts
@@ -0,0 +1,53 @@
+import path from 'path';
+import assert from 'assert';
+import { createApp } from './utils';
+import LifecycleList from './fixtures/app_with_lifecycle/lifecyclelist';
+
+describe('test/lifecycle.test.ts', () => {
+  it('should lifecycle works without error', async () => {
+    const appWithLifeCyclePath = path.resolve(__dirname, './fixtures/app_with_lifecycle');
+    const app = await createApp(appWithLifeCyclePath);
+    const lifecycleList = app.container.get(LifecycleList).lifecycleList;
+
+    assert.deepStrictEqual(lifecycleList, [
+      'pluginA_configWillLoad',
+      'pluginB_configWillLoad',
+      'app_configWillLoad',
+      'pluginA_configDidLoad',
+      'pluginB_configDidLoad',
+      'app_configDidLoad',
+      'pluginA_didLoad',
+      'pluginB_didLoad',
+      'app_didLoad',
+      'pluginA_willReady',
+      'pluginB_willReady',
+      'app_willReady',
+      'pluginA_didReady',
+      'pluginB_didReady',
+      'app_didReady',
+    ]);
+
+    await app.close();
+
+    assert.deepStrictEqual(lifecycleList, [
+      'pluginA_configWillLoad',
+      'pluginB_configWillLoad',
+      'app_configWillLoad',
+      'pluginA_configDidLoad',
+      'pluginB_configDidLoad',
+      'app_configDidLoad',
+      'pluginA_didLoad',
+      'pluginB_didLoad',
+      'app_didLoad',
+      'pluginA_willReady',
+      'pluginB_willReady',
+      'app_willReady',
+      'pluginA_didReady',
+      'pluginB_didReady',
+      'app_didReady',
+      'pluginA_beforeClose',
+      'pluginB_beforeClose',
+      'app_beforeClose',
+    ]);
+  });
+});
diff --git a/test/loader.test.ts b/test/loader.test.ts
index 30f13c7..db77cdd 100644
--- a/test/loader.test.ts
+++ b/test/loader.test.ts
@@ -4,8 +4,8 @@ import assert from 'assert';
 import path from 'path';
 import { Container } from '@artus/injection';
 import { LoaderFactory } from '../src';
-import { createApp } from './fixtures/custom_instance/index';
 import Custom from './fixtures/custom_instance/custom';
+import { createApp } from './utils';
 
 describe('test/loader.test.ts', () => {
   describe('module with ts', () => {
@@ -67,7 +67,7 @@ describe('test/loader.test.ts', () => {
 
   describe('custom instance', () => {
     it('should not overide custom instance', async () => {
-      const app = await createApp();
+      const app = await createApp(path.resolve(__dirname, './fixtures/custom_instance'));
       expect(app.container.get(Custom).getName()).toBe('foo');
     });
   });
diff --git a/test/fixtures/custom_instance/index.ts b/test/utils/index.ts
similarity index 68%
rename from test/fixtures/custom_instance/index.ts
rename to test/utils/index.ts
index dab3467..60fc90d 100644
--- a/test/fixtures/custom_instance/index.ts
+++ b/test/utils/index.ts
@@ -1,7 +1,7 @@
-import { Scanner, ArtusApplication } from '../../../src/index';
+import 'reflect-metadata';
+import { Scanner, ArtusApplication } from '../../src';
 
-export async function createApp() {
-  const baseDir = __dirname;
+export async function createApp(baseDir: string) {
   const scanner = new Scanner({
     needWriteFile: false,
     configDir: 'config',