From 4909a82b9924f28eb86682158487f8c1fbe3dd11 Mon Sep 17 00:00:00 2001 From: pgayvallet Date: Fri, 17 Jan 2020 09:10:25 +0100 Subject: [PATCH 1/5] implements server-side getStartServices --- src/core/server/index.ts | 9 ++++++++- src/core/server/legacy/legacy_service.ts | 12 +++++++----- src/core/server/mocks.ts | 7 ++++++- src/core/server/plugins/plugin.ts | 14 ++++++++++---- src/core/server/plugins/plugin_context.ts | 1 + x-pack/plugins/endpoint/server/plugin.test.ts | 4 ++-- x-pack/plugins/security/server/plugin.test.ts | 4 ++-- 7 files changed, 36 insertions(+), 15 deletions(-) diff --git a/src/core/server/index.ts b/src/core/server/index.ts index 50d291b173640..3f67b9a656bb7 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -283,7 +283,7 @@ export interface RequestHandlerContext { * * @public */ -export interface CoreSetup { +export interface CoreSetup { /** {@link CapabilitiesSetup} */ capabilities: CapabilitiesSetup; /** {@link ContextSetup} */ @@ -298,6 +298,13 @@ export interface CoreSetup { uiSettings: UiSettingsServiceSetup; /** {@link UuidServiceSetup} */ uuid: UuidServiceSetup; + /** + * Allows plugins to get access to APIs available in start inside async handlers. + * Promise will not resolve until Core and plugin dependencies have completed `start`. + * This should only be used inside handlers registered during `setup` that will only be executed + * after `start` lifecycle. + */ + getStartServices(): Promise<[CoreStart, TPluginsStart]>; } /** diff --git a/src/core/server/legacy/legacy_service.ts b/src/core/server/legacy/legacy_service.ts index ffcbf1662ee85..07cc933033054 100644 --- a/src/core/server/legacy/legacy_service.ts +++ b/src/core/server/legacy/legacy_service.ts @@ -256,6 +256,12 @@ export class LegacyService implements CoreService { startDeps: LegacyServiceStartDeps, legacyPlugins: LegacyPlugins ) { + const coreStart: CoreStart = { + capabilities: startDeps.core.capabilities, + savedObjects: { getScopedClient: startDeps.core.savedObjects.getScopedClient }, + uiSettings: { asScopedToClient: startDeps.core.uiSettings.asScopedToClient }, + }; + const coreSetup: CoreSetup = { capabilities: setupDeps.core.capabilities, context: setupDeps.core.context, @@ -291,11 +297,7 @@ export class LegacyService implements CoreService { uuid: { getInstanceUuid: setupDeps.core.uuid.getInstanceUuid, }, - }; - const coreStart: CoreStart = { - capabilities: startDeps.core.capabilities, - savedObjects: { getScopedClient: startDeps.core.savedObjects.getScopedClient }, - uiSettings: { asScopedToClient: startDeps.core.uiSettings.asScopedToClient }, + getStartServices: () => Promise.resolve([coreStart, startDeps.plugins]), }; // eslint-disable-next-line @typescript-eslint/no-var-requires diff --git a/src/core/server/mocks.ts b/src/core/server/mocks.ts index c7082d46313ae..c0a8973d98a54 100644 --- a/src/core/server/mocks.ts +++ b/src/core/server/mocks.ts @@ -86,6 +86,8 @@ function pluginInitializerContextMock(config: T = {} as T) { return mock; } +type CoreSetupMockType = MockedKeys & jest.Mocked>; + function createCoreSetupMock() { const httpService = httpServiceMock.createSetupContract(); const httpMock: jest.Mocked = { @@ -105,7 +107,7 @@ function createCoreSetupMock() { const uiSettingsMock = { register: uiSettingsServiceMock.createSetupContract().register, }; - const mock: MockedKeys = { + const mock: CoreSetupMockType = { capabilities: capabilitiesServiceMock.createSetupContract(), context: contextServiceMock.createSetupContract(), elasticsearch: elasticsearchServiceMock.createSetup(), @@ -113,6 +115,9 @@ function createCoreSetupMock() { savedObjects: savedObjectsServiceMock.createSetupContract(), uiSettings: uiSettingsMock, uuid: uuidServiceMock.createSetupContract(), + getStartServices: jest + .fn, object]>, []>() + .mockResolvedValue([createCoreStartMock(), {}]), }; return mock; diff --git a/src/core/server/plugins/plugin.ts b/src/core/server/plugins/plugin.ts index c0b484515ccce..1e57f2581f096 100644 --- a/src/core/server/plugins/plugin.ts +++ b/src/core/server/plugins/plugin.ts @@ -19,7 +19,8 @@ import { join } from 'path'; import typeDetect from 'type-detect'; - +import { Subject } from 'rxjs'; +import { first } from 'rxjs/operators'; import { Type } from '@kbn/config-schema'; import { Logger } from '../logging'; @@ -60,6 +61,9 @@ export class PluginWrapper< private instance?: Plugin; + private readonly startDependencies$ = new Subject<[CoreStart, TPluginsStart]>(); + public readonly startDependencies = this.startDependencies$.pipe(first()).toPromise(); + constructor( public readonly params: { readonly path: string; @@ -88,12 +92,12 @@ export class PluginWrapper< * @param plugins The dictionary where the key is the dependency name and the value * is the contract returned by the dependency's `setup` function. */ - public async setup(setupContext: CoreSetup, plugins: TPluginsSetup) { + public async setup(setupContext: CoreSetup, plugins: TPluginsSetup) { this.instance = this.createPluginInstance(); this.log.info('Setting up plugin'); - return await this.instance.setup(setupContext, plugins); + return await this.instance.setup(setupContext, plugins); // todo: remove await } /** @@ -108,7 +112,9 @@ export class PluginWrapper< throw new Error(`Plugin "${this.name}" can't be started since it isn't set up.`); } - return await this.instance.start(startContext, plugins); + const startContract = await this.instance.start(startContext, plugins); + this.startDependencies$.next([startContext, plugins]); + return startContract; } /** diff --git a/src/core/server/plugins/plugin_context.ts b/src/core/server/plugins/plugin_context.ts index 6d82a8d3ec6cf..f266172cb4bd9 100644 --- a/src/core/server/plugins/plugin_context.ts +++ b/src/core/server/plugins/plugin_context.ts @@ -176,6 +176,7 @@ export function createPluginSetupContext( uuid: { getInstanceUuid: deps.uuid.getInstanceUuid, }, + getStartServices: () => plugin.startDependencies, }; } diff --git a/x-pack/plugins/endpoint/server/plugin.test.ts b/x-pack/plugins/endpoint/server/plugin.test.ts index 87d373d3a4f34..7dd878d579043 100644 --- a/x-pack/plugins/endpoint/server/plugin.test.ts +++ b/x-pack/plugins/endpoint/server/plugin.test.ts @@ -3,14 +3,14 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { CoreSetup } from 'kibana/server'; + import { EndpointPlugin, EndpointPluginSetupDependencies } from './plugin'; import { coreMock } from '../../../../src/core/server/mocks'; import { PluginSetupContract } from '../../features/server'; describe('test endpoint plugin', () => { let plugin: EndpointPlugin; - let mockCoreSetup: MockedKeys; + let mockCoreSetup: ReturnType; let mockedEndpointPluginSetupDependencies: jest.Mocked; let mockedPluginSetupContract: jest.Mocked; beforeEach(() => { diff --git a/x-pack/plugins/security/server/plugin.test.ts b/x-pack/plugins/security/server/plugin.test.ts index 5e32a0e90198a..56aad4ece3e95 100644 --- a/x-pack/plugins/security/server/plugin.test.ts +++ b/x-pack/plugins/security/server/plugin.test.ts @@ -6,7 +6,7 @@ import { of } from 'rxjs'; import { ByteSizeValue } from '@kbn/config-schema'; -import { ICustomClusterClient, CoreSetup } from '../../../../src/core/server'; +import { ICustomClusterClient } from '../../../../src/core/server'; import { elasticsearchClientPlugin } from './elasticsearch_client_plugin'; import { Plugin, PluginSetupDependencies } from './plugin'; @@ -14,7 +14,7 @@ import { coreMock, elasticsearchServiceMock } from '../../../../src/core/server/ describe('Security Plugin', () => { let plugin: Plugin; - let mockCoreSetup: MockedKeys; + let mockCoreSetup: ReturnType; let mockClusterClient: jest.Mocked; let mockDependencies: PluginSetupDependencies; beforeEach(() => { From 2d60b09be01f836c10ea4db715a6c356e03222dc Mon Sep 17 00:00:00 2001 From: pgayvallet Date: Fri, 17 Jan 2020 09:48:53 +0100 Subject: [PATCH 2/5] add unit test --- src/core/server/plugins/plugin.test.ts | 37 ++++++++++++++++++++++++++ src/core/server/plugins/plugin.ts | 2 +- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/core/server/plugins/plugin.test.ts b/src/core/server/plugins/plugin.test.ts index 10259b718577c..6875302f88a9d 100644 --- a/src/core/server/plugins/plugin.test.ts +++ b/src/core/server/plugins/plugin.test.ts @@ -237,6 +237,43 @@ test('`start` calls plugin.start with context and dependencies', async () => { expect(mockPluginInstance.start).toHaveBeenCalledWith(context, deps); }); +test("`start` resolves `startDependencies` Promise after plugin's start", async () => { + expect.assertions(2); + + const manifest = createPluginManifest(); + const opaqueId = Symbol(); + const plugin = new PluginWrapper({ + path: 'plugin-with-initializer-path', + manifest, + opaqueId, + initializerContext: createPluginInitializerContext(coreContext, opaqueId, manifest), + }); + const startContext = { any: 'thing' } as any; + const pluginDeps = { someDep: 'value' }; + + let startDependenciesResolved = false; + + const mockPluginInstance = { + setup: jest.fn(), + start: async () => { + // delay to ensure startDependencies is not resolved until after the plugin instance's start resolves. + await new Promise(resolve => setTimeout(resolve, 10)); + expect(startDependenciesResolved).toBe(false); + }, + }; + mockPluginInitializer.mockReturnValue(mockPluginInstance); + + await plugin.setup({} as any, {} as any); + + const startDependenciesCheck = plugin.startDependencies.then(resolvedStartDeps => { + startDependenciesResolved = true; + expect(resolvedStartDeps).toEqual([startContext, pluginDeps]); + }); + + await plugin.start(startContext, pluginDeps); + await startDependenciesCheck; +}); + test('`stop` fails if plugin is not set up', async () => { const manifest = createPluginManifest(); const opaqueId = Symbol(); diff --git a/src/core/server/plugins/plugin.ts b/src/core/server/plugins/plugin.ts index 1e57f2581f096..d6c774f6fc41c 100644 --- a/src/core/server/plugins/plugin.ts +++ b/src/core/server/plugins/plugin.ts @@ -97,7 +97,7 @@ export class PluginWrapper< this.log.info('Setting up plugin'); - return await this.instance.setup(setupContext, plugins); // todo: remove await + return this.instance.setup(setupContext, plugins); } /** From dbe6b505b6b9a24c86caa946386c34480423fc16 Mon Sep 17 00:00:00 2001 From: pgayvallet Date: Fri, 17 Jan 2020 10:46:54 +0100 Subject: [PATCH 3/5] add integration test --- .../plugins_service.test.mocks.ts | 27 +++ .../integration_tests/plugins_service.test.ts | 161 ++++++++++++++++++ 2 files changed, 188 insertions(+) create mode 100644 src/core/server/plugins/integration_tests/plugins_service.test.mocks.ts create mode 100644 src/core/server/plugins/integration_tests/plugins_service.test.ts diff --git a/src/core/server/plugins/integration_tests/plugins_service.test.mocks.ts b/src/core/server/plugins/integration_tests/plugins_service.test.mocks.ts new file mode 100644 index 0000000000000..d81a7eb5db4ae --- /dev/null +++ b/src/core/server/plugins/integration_tests/plugins_service.test.mocks.ts @@ -0,0 +1,27 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export const mockPackage = new Proxy( + { raw: { __dirname: '/tmp' } as any }, + { get: (obj, prop) => obj.raw[prop] } +); +jest.mock('../../../../core/server/utils/package_json', () => ({ pkg: mockPackage })); + +export const mockDiscover = jest.fn(); +jest.mock('../discovery/plugins_discovery', () => ({ discover: mockDiscover })); diff --git a/src/core/server/plugins/integration_tests/plugins_service.test.ts b/src/core/server/plugins/integration_tests/plugins_service.test.ts new file mode 100644 index 0000000000000..8d85b703f8fd1 --- /dev/null +++ b/src/core/server/plugins/integration_tests/plugins_service.test.ts @@ -0,0 +1,161 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { mockPackage, mockDiscover } from './plugins_service.test.mocks'; + +import { join } from 'path'; + +import { PluginsService } from '../plugins_service'; +import { ConfigPath, ConfigService, Env } from '../../config'; +import { getEnvOptions } from '../../config/__mocks__/env'; +import { BehaviorSubject, from } from 'rxjs'; +import { rawConfigServiceMock } from '../../config/raw_config_service.mock'; +import { config } from '../plugins_config'; +import { loggingServiceMock } from '../../logging/logging_service.mock'; +import { coreMock } from '../../mocks'; +import { Plugin } from '../types'; +import { PluginWrapper } from '../plugin'; + +describe('PluginsService', () => { + const logger = loggingServiceMock.create(); + let pluginsService: PluginsService; + + const createPlugin = ( + id: string, + { + path = id, + disabled = false, + version = 'some-version', + requiredPlugins = [], + optionalPlugins = [], + kibanaVersion = '7.0.0', + configPath = [path], + server = true, + ui = true, + }: { + path?: string; + disabled?: boolean; + version?: string; + requiredPlugins?: string[]; + optionalPlugins?: string[]; + kibanaVersion?: string; + configPath?: ConfigPath; + server?: boolean; + ui?: boolean; + } + ): PluginWrapper => { + return new PluginWrapper({ + path, + manifest: { + id, + version, + configPath: `${configPath}${disabled ? '-disabled' : ''}`, + kibanaVersion, + requiredPlugins, + optionalPlugins, + server, + ui, + }, + opaqueId: Symbol(id), + initializerContext: { logger } as any, + }); + }; + + beforeEach(async () => { + mockPackage.raw = { + branch: 'feature-v1', + version: 'v1', + build: { + distributable: true, + number: 100, + sha: 'feature-v1-build-sha', + }, + }; + + const env = Env.createDefault(getEnvOptions()); + const config$ = new BehaviorSubject>({ + plugins: { + initialize: true, + }, + }); + const rawConfigService = rawConfigServiceMock.create({ rawConfig$: config$ }); + const configService = new ConfigService(rawConfigService, env, logger); + await configService.setSchema(config.path, config.schema); + + pluginsService = new PluginsService({ + coreId: Symbol('core'), + env, + logger, + configService, + }); + }); + + it("properly resolves `getStartServices` in plugin's lifecycle", async () => { + expect.assertions(3); + + const pluginPath = 'plugin-path'; + + mockDiscover.mockReturnValue({ + error$: from([]), + plugin$: from([ + createPlugin('plugin-id', { + path: pluginPath, + configPath: 'path', + }), + ]), + }); + + let startDependenciesResolved = false; + + const pluginInitializer = () => + ({ + setup: async (core, deps) => { + core.getStartServices().then(([coreStart, pluginDeps]) => { + startDependenciesResolved = true; + }); + }, + start: async (core, deps) => { + await new Promise(resolve => setTimeout(resolve, 10)); + expect(startDependenciesResolved).toBe(false); + }, + } as Plugin); + + jest.doMock( + join(pluginPath, 'server'), + () => ({ + plugin: pluginInitializer, + }), + { + virtual: true, + } + ); + + await pluginsService.discover(); + + const setupDeps = coreMock.createInternalSetup(); + await pluginsService.setup(setupDeps); + + expect(startDependenciesResolved).toBe(false); + + const startDeps = coreMock.createInternalStart(); + await pluginsService.start(startDeps); + + expect(startDependenciesResolved).toBe(true); + }); +}); From 7e02978f7a580c24969cd2038698098fe6e67051 Mon Sep 17 00:00:00 2001 From: pgayvallet Date: Fri, 17 Jan 2020 10:52:57 +0100 Subject: [PATCH 4/5] update generated doc --- ...lugin-server.coresetup.getstartservices.md | 17 ++++++ .../server/kibana-plugin-server.coresetup.md | 58 ++++++++++--------- src/core/server/server.api.md | 3 +- 3 files changed, 51 insertions(+), 27 deletions(-) create mode 100644 docs/development/core/server/kibana-plugin-server.coresetup.getstartservices.md diff --git a/docs/development/core/server/kibana-plugin-server.coresetup.getstartservices.md b/docs/development/core/server/kibana-plugin-server.coresetup.getstartservices.md new file mode 100644 index 0000000000000..b05d28899f9d2 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.coresetup.getstartservices.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CoreSetup](./kibana-plugin-server.coresetup.md) > [getStartServices](./kibana-plugin-server.coresetup.getstartservices.md) + +## CoreSetup.getStartServices() method + +Allows plugins to get access to APIs available in start inside async handlers. Promise will not resolve until Core and plugin dependencies have completed `start`. This should only be used inside handlers registered during `setup` that will only be executed after `start` lifecycle. + +Signature: + +```typescript +getStartServices(): Promise<[CoreStart, TPluginsStart]>; +``` +Returns: + +`Promise<[CoreStart, TPluginsStart]>` + diff --git a/docs/development/core/server/kibana-plugin-server.coresetup.md b/docs/development/core/server/kibana-plugin-server.coresetup.md index 3f7f5b727ee80..c36d649837e8a 100644 --- a/docs/development/core/server/kibana-plugin-server.coresetup.md +++ b/docs/development/core/server/kibana-plugin-server.coresetup.md @@ -1,26 +1,32 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CoreSetup](./kibana-plugin-server.coresetup.md) - -## CoreSetup interface - -Context passed to the plugins `setup` method. - -Signature: - -```typescript -export interface CoreSetup -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [capabilities](./kibana-plugin-server.coresetup.capabilities.md) | CapabilitiesSetup | [CapabilitiesSetup](./kibana-plugin-server.capabilitiessetup.md) | -| [context](./kibana-plugin-server.coresetup.context.md) | ContextSetup | [ContextSetup](./kibana-plugin-server.contextsetup.md) | -| [elasticsearch](./kibana-plugin-server.coresetup.elasticsearch.md) | ElasticsearchServiceSetup | [ElasticsearchServiceSetup](./kibana-plugin-server.elasticsearchservicesetup.md) | -| [http](./kibana-plugin-server.coresetup.http.md) | HttpServiceSetup | [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) | -| [savedObjects](./kibana-plugin-server.coresetup.savedobjects.md) | SavedObjectsServiceSetup | [SavedObjectsServiceSetup](./kibana-plugin-server.savedobjectsservicesetup.md) | -| [uiSettings](./kibana-plugin-server.coresetup.uisettings.md) | UiSettingsServiceSetup | [UiSettingsServiceSetup](./kibana-plugin-server.uisettingsservicesetup.md) | -| [uuid](./kibana-plugin-server.coresetup.uuid.md) | UuidServiceSetup | [UuidServiceSetup](./kibana-plugin-server.uuidservicesetup.md) | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CoreSetup](./kibana-plugin-server.coresetup.md) + +## CoreSetup interface + +Context passed to the plugins `setup` method. + +Signature: + +```typescript +export interface CoreSetup +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [capabilities](./kibana-plugin-server.coresetup.capabilities.md) | CapabilitiesSetup | [CapabilitiesSetup](./kibana-plugin-server.capabilitiessetup.md) | +| [context](./kibana-plugin-server.coresetup.context.md) | ContextSetup | [ContextSetup](./kibana-plugin-server.contextsetup.md) | +| [elasticsearch](./kibana-plugin-server.coresetup.elasticsearch.md) | ElasticsearchServiceSetup | [ElasticsearchServiceSetup](./kibana-plugin-server.elasticsearchservicesetup.md) | +| [http](./kibana-plugin-server.coresetup.http.md) | HttpServiceSetup | [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) | +| [savedObjects](./kibana-plugin-server.coresetup.savedobjects.md) | SavedObjectsServiceSetup | [SavedObjectsServiceSetup](./kibana-plugin-server.savedobjectsservicesetup.md) | +| [uiSettings](./kibana-plugin-server.coresetup.uisettings.md) | UiSettingsServiceSetup | [UiSettingsServiceSetup](./kibana-plugin-server.uisettingsservicesetup.md) | +| [uuid](./kibana-plugin-server.coresetup.uuid.md) | UuidServiceSetup | [UuidServiceSetup](./kibana-plugin-server.uuidservicesetup.md) | + +## Methods + +| Method | Description | +| --- | --- | +| [getStartServices()](./kibana-plugin-server.coresetup.getstartservices.md) | Allows plugins to get access to APIs available in start inside async handlers. Promise will not resolve until Core and plugin dependencies have completed start. This should only be used inside handlers registered during setup that will only be executed after start lifecycle. | + diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 6a58666716f42..182434134ae2b 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -552,13 +552,14 @@ export interface ContextSetup { export type CoreId = symbol; // @public -export interface CoreSetup { +export interface CoreSetup { // (undocumented) capabilities: CapabilitiesSetup; // (undocumented) context: ContextSetup; // (undocumented) elasticsearch: ElasticsearchServiceSetup; + getStartServices(): Promise<[CoreStart, TPluginsStart]>; // (undocumented) http: HttpServiceSetup; // (undocumented) From ea959058d043b5023fd4dfef103c12464eec7b28 Mon Sep 17 00:00:00 2001 From: pgayvallet Date: Mon, 20 Jan 2020 08:39:23 +0100 Subject: [PATCH 5/5] improve test --- .../integration_tests/plugins_service.test.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/core/server/plugins/integration_tests/plugins_service.test.ts b/src/core/server/plugins/integration_tests/plugins_service.test.ts index 8d85b703f8fd1..d5531478f03c5 100644 --- a/src/core/server/plugins/integration_tests/plugins_service.test.ts +++ b/src/core/server/plugins/integration_tests/plugins_service.test.ts @@ -107,7 +107,7 @@ describe('PluginsService', () => { }); it("properly resolves `getStartServices` in plugin's lifecycle", async () => { - expect.assertions(3); + expect.assertions(5); const pluginPath = 'plugin-path'; @@ -122,15 +122,19 @@ describe('PluginsService', () => { }); let startDependenciesResolved = false; + let contextFromStart: any = null; + let contextFromStartService: any = null; const pluginInitializer = () => ({ - setup: async (core, deps) => { - core.getStartServices().then(([coreStart, pluginDeps]) => { + setup: async (coreSetup, deps) => { + coreSetup.getStartServices().then(([core, plugins]) => { startDependenciesResolved = true; + contextFromStartService = { core, plugins }; }); }, - start: async (core, deps) => { + start: async (core, plugins) => { + contextFromStart = { core, plugins }; await new Promise(resolve => setTimeout(resolve, 10)); expect(startDependenciesResolved).toBe(false); }, @@ -157,5 +161,7 @@ describe('PluginsService', () => { await pluginsService.start(startDeps); expect(startDependenciesResolved).toBe(true); + expect(contextFromStart!.core).toEqual(contextFromStartService!.core); + expect(contextFromStart!.plugins).toEqual(contextFromStartService!.plugins); }); });