import { REPO_ROOT } from '@osd/dev-utils' ; 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 , rawConfigServiceMock } from '../../config/mocks' ; import { BehaviorSubject , from } from 'rxjs' ; import { config } from '../plugins_config' ; import { loggingSystemMock } from '../../logging/logging_system.mock' ; import { environmentServiceMock } from '../../environment/environment_service.mock' ; import { coreMock } from '../../mocks' ; import { Plugin } from '../types' ; import { PluginWrapper } from '../plugin' ; describe ( 'PluginsService' , ( ) => { const logger = loggingSystemMock . create ( ) ; const environmentSetup = environmentServiceMock . createSetupContract ( ) ; let pluginsService ; const createPlugin = ( id , { path = id , disabled = false , version = 'some-version' , requiredPlugins = [ ] , requiredBundles = [ ] , optionalPlugins = [ ] , opensearchDashboardsVersion = '7.0.0' , configPath = [ path ] , server = true , ui = true , } ) : PluginWrapper => { return new PluginWrapper ( { path , manifest : { id , version , configPath : `${ configPath }${ disabled ? '-disabled' : '' }` , opensearchDashboardsVersion , requiredPlugins , requiredBundles , 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 ( REPO_ROOT , getEnvOptions ( ) ) ; const config$ = new BehaviorSubject < Record < string , any > > ( { 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 ( 6 ) ; const pluginPath = 'plugin-path' ; mockDiscover . mockReturnValue ( { error$ : from ( [ ] ) , plugin$ : from ( [ createPlugin ( 'plugin-id' , { path : pluginPath , configPath : 'path' , } ) , ] ) , } ) ; let startDependenciesResolved = false ; let contextFromStart = null ; let contextFromStartService = null ; const pluginStartContract = { someApi : ( ) => 'foo' , } ; const pluginInitializer = ( ) => ( { setup : async ( coreSetup , deps ) => { coreSetup . getStartServices ( ) . then ( ( [ core , plugins , pluginStart ] ) => { startDependenciesResolved = true ; contextFromStartService = { core , plugins , pluginStart } ; } ) ; } , start : async ( core , plugins ) => { contextFromStart = { core , plugins } ; await new Promise ( ( resolve ) => setTimeout ( resolve , 10 ) ) ; expect ( startDependenciesResolved ) . toBe ( false ) ; return pluginStartContract ; } , } as Plugin < void , typeof pluginStartContract , { } , { } > ) ; jest . doMock ( join ( pluginPath , 'server' ) , ( ) => ( { plugin : pluginInitializer , } ) , { virtual : true , } ) ; await pluginsService . discover ( { environment : environmentSetup } ) ; const setupDeps = coreMock . createInternalSetup ( ) ; await pluginsService . setup ( setupDeps ) ; expect ( startDependenciesResolved ) . toBe ( false ) ; const startDeps = coreMock . createInternalStart ( ) ; await pluginsService . start ( startDeps ) ; expect ( startDependenciesResolved ) . toBe ( true ) ; expect ( contextFromStart ! . core ) . toEqual ( contextFromStartService ! . core ) ; expect ( contextFromStart ! . plugins ) . toEqual ( contextFromStartService ! . plugins ) ; expect ( contextFromStartService ! . pluginStart ) . toEqual ( pluginStartContract ) ; } ) ; } ) ;