浏览代码

AppPlugin: add an init function (#17150)

Ryan McKinley 6 年之前
父节点
当前提交
7e3ac4ebde

+ 7 - 0
packages/grafana-ui/src/types/app.ts

@@ -26,6 +26,13 @@ export class AppPlugin extends GrafanaPlugin<AppPluginMeta> {
   // Old style pages
   angularPages?: { [component: string]: any };
 
+  /**
+   * Called after the module has loaded, and before the app is used.
+   * This function may be called multiple times on the same instance.
+   * The first time, `this.meta` will be undefined
+   */
+  init(meta: AppPluginMeta) {}
+
   /**
    * Set the component displayed under:
    *   /a/${plugin-id}/*

+ 68 - 0
public/app/features/plugins/plugin_loader.test.ts

@@ -0,0 +1,68 @@
+// Use the real plugin_loader (stubbed by default)
+jest.unmock('app/features/plugins/plugin_loader');
+
+(global as any).ace = {
+  define: jest.fn(),
+};
+
+jest.mock('app/core/core', () => {
+  return {
+    coreModule: {
+      directive: jest.fn(),
+    },
+  };
+});
+
+/* tslint:disable:import-blacklist */
+import System from 'systemjs/dist/system.js';
+
+import { AppPluginMeta, PluginMetaInfo, PluginType, AppPlugin } from '@grafana/ui';
+import { importAppPlugin } from './plugin_loader';
+
+class MyCustomApp extends AppPlugin {
+  initWasCalled = false;
+  calledTwice = false;
+
+  init(meta: AppPluginMeta) {
+    this.initWasCalled = true;
+    this.calledTwice = this.meta === meta;
+  }
+}
+
+describe('Load App', () => {
+  const app = new MyCustomApp();
+  const modulePath = 'my/custom/plugin/module';
+
+  beforeAll(() => {
+    System.set(modulePath, System.newModule({ plugin: app }));
+  });
+
+  afterAll(() => {
+    System.delete(modulePath);
+  });
+
+  it('should call init and set meta', async () => {
+    const meta: AppPluginMeta = {
+      id: 'test-app',
+      module: modulePath,
+      baseUrl: 'xxx',
+      info: {} as PluginMetaInfo,
+      type: PluginType.app,
+      name: 'test',
+    };
+
+    // Check that we mocked the import OK
+    const m = await System.import(modulePath);
+    expect(m.plugin).toBe(app);
+
+    const loaded = await importAppPlugin(meta);
+    expect(loaded).toBe(app);
+    expect(app.meta).toBe(meta);
+    expect(app.initWasCalled).toBeTruthy();
+    expect(app.calledTwice).toBeFalsy();
+
+    const again = await importAppPlugin(meta);
+    expect(again).toBe(app);
+    expect(app.calledTwice).toBeTruthy();
+  });
+});

+ 2 - 1
public/app/features/plugins/plugin_loader.ts

@@ -181,8 +181,9 @@ export function importDataSourcePlugin(meta: DataSourcePluginMeta): Promise<Data
 export function importAppPlugin(meta: PluginMeta): Promise<AppPlugin> {
   return importPluginModule(meta.module).then(pluginExports => {
     const plugin = pluginExports.plugin ? (pluginExports.plugin as AppPlugin) : new AppPlugin();
-    plugin.meta = meta;
     plugin.setComponentsFromLegacyExports(pluginExports);
+    plugin.init(meta);
+    plugin.meta = meta;
     return plugin;
   });
 }