diff --git a/src/plug.ts b/src/plug.ts index 27400eb51..870073275 100644 --- a/src/plug.ts +++ b/src/plug.ts @@ -7,6 +7,7 @@ import Tracker from '@croct/sdk/facade/trackerFacade'; import {EvaluationOptions} from '@croct/sdk/facade/evaluatorFacade'; import Sdk, {Configuration as SdkFacadeConfiguration} from '@croct/sdk/facade/sdkFacade'; import {formatCause} from '@croct/sdk/error'; +import {describe} from '@croct/sdk/validation'; import {Plugin, PluginArguments, PluginFactory} from './plugin'; interface PluginConfigurations { @@ -100,8 +101,23 @@ export class GlobalPlug implements Plug { continue; } + if (typeof options !== 'boolean' && (options === null || typeof options !== 'object')) { + logger.error( + `Invalid options for plugin "${name}", ` + + `expected either boolean or object but got ${describe(options)}`, + ); + + continue; + } + + if (options === false) { + logger.warn(`Plugin "${name}" is declared but not enabled`); + + continue; + } + const args: PluginArguments = { - options: options, + options: options === true ? {} : options, sdk: { tracker: sdk.tracker, evaluator: sdk.evaluator, diff --git a/test/plug.test.ts b/test/plug.test.ts index a09282278..fac708d0c 100644 --- a/test/plug.test.ts +++ b/test/plug.test.ts @@ -72,10 +72,12 @@ describe('The Croct plug', () => { plugins: {foo: true}, }); - expect(logger.error).toBeCalledWith('[Croct] Failed to initialize plugin "foo": failure'); + expect(logger.error).toBeCalledWith( + expect.stringContaining('Failed to initialize plugin "foo": failure'), + ); }); - test('should log an error if a plugin is not registered', async () => { + test('should log an error if a plugin is not registered', () => { const logger: Logger = { debug: jest.fn(), info: jest.fn(), @@ -89,14 +91,62 @@ describe('The Croct plug', () => { logger: logger, }); - await croct.plugged; - expect(logger.error).toHaveBeenCalledWith( expect.stringContaining('Plugin "foo" is not registered.'), ); }); - test('should initialize the specified plugins', () => { + test('should log an error if a plugin options is invalid', () => { + const logger: Logger = { + debug: jest.fn(), + info: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }; + + const factory: PluginFactory = jest.fn(); + + croct.extend('foo', factory); + + croct.plug({ + appId: appId, + plugins: {foo: null}, + logger: logger, + }); + + expect(factory).not.toHaveBeenCalled(); + + expect(logger.error).toHaveBeenCalledWith( + expect.stringContaining('Invalid options for plugin "foo", expected either boolean or object but got null'), + ); + }); + + test('should not initialize disabled plugins', () => { + const factory: PluginFactory = jest.fn(); + + croct.extend('foo', factory); + + const logger: Logger = { + debug: jest.fn(), + info: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }; + + croct.plug({ + appId: appId, + logger: logger, + plugins: {foo: false}, + }); + + expect(factory).not.toHaveBeenCalled(); + + expect(logger.warn).toBeCalledWith( + expect.stringContaining('Plugin "foo" is declared but not enabled'), + ); + }); + + test('should initialize the declared plugins', () => { const fooFactory: PluginFactory = jest.fn().mockImplementation(({sdk}) => { sdk.getLogger('namespace'); sdk.getTabStorage('namespace'); @@ -121,14 +171,14 @@ describe('The Croct plug', () => { appId: appId, plugins: { foo: true, - bar: false, + bar: {flag: true}, }, }); expect(initialize).toBeCalledWith(config); - expect(fooFactory).toBeCalledWith(expect.objectContaining({options: true})); - expect(barFactory).toBeCalledWith(expect.objectContaining({options: false})); + expect(fooFactory).toBeCalledWith(expect.objectContaining({options: {}})); + expect(barFactory).toBeCalledWith(expect.objectContaining({options: {flag: true}})); expect(getLogger).toBeCalledWith('Plugin', 'foo', 'namespace'); expect(getTabStorage).toBeCalledWith('Plugin', 'foo', 'namespace');