refactor(plugins): switched from require to await import() when loading plugins (#2558)
				
					
				
			This commit is contained in:
		
							parent
							
								
									466898b3b4
								
							
						
					
					
						commit
						4cd3641dbf
					
				| @ -68,7 +68,7 @@ Your configuration for the \`${type}\` plugin is \`${stringify(pluginConf)}\`.`, | |||||||
|     message: 'The `plugins` configuration is invalid.', |     message: 'The `plugins` configuration is invalid.', | ||||||
|     details: `The [plugins](${linkify( |     details: `The [plugins](${linkify( | ||||||
|       'docs/usage/configuration.md#plugins' |       'docs/usage/configuration.md#plugins' | ||||||
|     )}) option must be an array of plugin definions. A plugin definition is an npm module name, optionally wrapped in an array with an object. |     )}) option must be an array of plugin definitions. A plugin definition is an npm module name, optionally wrapped in an array with an object. | ||||||
| 
 | 
 | ||||||
| The invalid configuration is \`${stringify(plugin)}\`.`, | The invalid configuration is \`${stringify(plugin)}\`.`, | ||||||
|   }), |   }), | ||||||
|  | |||||||
| @ -6,15 +6,16 @@ const {validatePlugin, validateStep, loadPlugin, parseConfig} = require('./utils | |||||||
| const pipeline = require('./pipeline'); | const pipeline = require('./pipeline'); | ||||||
| const normalize = require('./normalize'); | const normalize = require('./normalize'); | ||||||
| 
 | 
 | ||||||
| module.exports = (context, pluginsPath) => { | module.exports = async (context, pluginsPath) => { | ||||||
|   let {options, logger} = context; |   let {options, logger} = context; | ||||||
|   const errors = []; |   const errors = []; | ||||||
| 
 | 
 | ||||||
|   const plugins = options.plugins |   const plugins = options.plugins | ||||||
|     ? castArray(options.plugins).reduce((plugins, plugin) => { |     ? await castArray(options.plugins).reduce(async (eventualPluginsList, plugin) => { | ||||||
|  |         const pluginsList = await eventualPluginsList; | ||||||
|         if (validatePlugin(plugin)) { |         if (validatePlugin(plugin)) { | ||||||
|           const [name, config] = parseConfig(plugin); |           const [name, config] = parseConfig(plugin); | ||||||
|           plugin = isString(name) ? loadPlugin(context, name, pluginsPath) : name; |           plugin = isString(name) ? await loadPlugin(context, name, pluginsPath) : name; | ||||||
| 
 | 
 | ||||||
|           if (isPlainObject(plugin)) { |           if (isPlainObject(plugin)) { | ||||||
|             Object.entries(plugin).forEach(([type, func]) => { |             Object.entries(plugin).forEach(([type, func]) => { | ||||||
| @ -24,7 +25,7 @@ module.exports = (context, pluginsPath) => { | |||||||
|                   writable: false, |                   writable: false, | ||||||
|                   enumerable: true, |                   enumerable: true, | ||||||
|                 }); |                 }); | ||||||
|                 plugins[type] = [...(plugins[type] || []), [func, config]]; |                 pluginsList[type] = [...(pluginsList[type] || []), [func, config]]; | ||||||
|               } |               } | ||||||
|             }); |             }); | ||||||
|           } else { |           } else { | ||||||
| @ -34,7 +35,7 @@ module.exports = (context, pluginsPath) => { | |||||||
|           errors.push(getError('EPLUGINSCONF', {plugin})); |           errors.push(getError('EPLUGINSCONF', {plugin})); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return plugins; |         return pluginsList; | ||||||
|       }, {}) |       }, {}) | ||||||
|     : []; |     : []; | ||||||
| 
 | 
 | ||||||
| @ -44,9 +45,13 @@ module.exports = (context, pluginsPath) => { | |||||||
| 
 | 
 | ||||||
|   options = {...plugins, ...options}; |   options = {...plugins, ...options}; | ||||||
| 
 | 
 | ||||||
|   const pluginsConf = Object.entries(PLUGINS_DEFINITIONS).reduce( |   const pluginsConfig = await Object.entries(PLUGINS_DEFINITIONS).reduce( | ||||||
|     (pluginsConf, [type, {required, default: def, pipelineConfig, postprocess = identity, preprocess = identity}]) => { |     async ( | ||||||
|  |       eventualPluginsConfigAccumulator, | ||||||
|  |       [type, {required, default: def, pipelineConfig, postprocess = identity, preprocess = identity}] | ||||||
|  |     ) => { | ||||||
|       let pluginOptions; |       let pluginOptions; | ||||||
|  |       const pluginsConfigAccumulator = await eventualPluginsConfigAccumulator; | ||||||
| 
 | 
 | ||||||
|       if (isNil(options[type]) && def) { |       if (isNil(options[type]) && def) { | ||||||
|         pluginOptions = def; |         pluginOptions = def; | ||||||
| @ -60,28 +65,33 @@ module.exports = (context, pluginsPath) => { | |||||||
| 
 | 
 | ||||||
|         if (!validateStep({required}, options[type])) { |         if (!validateStep({required}, options[type])) { | ||||||
|           errors.push(getError('EPLUGINCONF', {type, required, pluginConf: options[type]})); |           errors.push(getError('EPLUGINCONF', {type, required, pluginConf: options[type]})); | ||||||
|           return pluginsConf; |           return pluginsConfigAccumulator; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         pluginOptions = options[type]; |         pluginOptions = options[type]; | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       const steps = castArray(pluginOptions).map((pluginOpt) => |       const steps = await Promise.all( | ||||||
|  |         castArray(pluginOptions).map(async (pluginOpt) => | ||||||
|           normalize( |           normalize( | ||||||
|             {...context, options: omit(options, Object.keys(PLUGINS_DEFINITIONS), 'plugins')}, |             {...context, options: omit(options, Object.keys(PLUGINS_DEFINITIONS), 'plugins')}, | ||||||
|             type, |             type, | ||||||
|             pluginOpt, |             pluginOpt, | ||||||
|             pluginsPath |             pluginsPath | ||||||
|           ) |           ) | ||||||
|  |         ) | ||||||
|       ); |       ); | ||||||
| 
 | 
 | ||||||
|       pluginsConf[type] = async (input) => |       pluginsConfigAccumulator[type] = async (input) => | ||||||
|         postprocess( |         postprocess( | ||||||
|           await pipeline(steps, pipelineConfig && pipelineConfig(pluginsConf, logger))(await preprocess(input)), |           await pipeline( | ||||||
|  |             steps, | ||||||
|  |             pipelineConfig && pipelineConfig(pluginsConfigAccumulator, logger) | ||||||
|  |           )(await preprocess(input)), | ||||||
|           input |           input | ||||||
|         ); |         ); | ||||||
| 
 | 
 | ||||||
|       return pluginsConf; |       return pluginsConfigAccumulator; | ||||||
|     }, |     }, | ||||||
|     plugins |     plugins | ||||||
|   ); |   ); | ||||||
| @ -89,5 +99,5 @@ module.exports = (context, pluginsPath) => { | |||||||
|     throw new AggregateError(errors); |     throw new AggregateError(errors); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   return pluginsConf; |   return pluginsConfig; | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -5,7 +5,7 @@ const {extractErrors} = require('../utils'); | |||||||
| const PLUGINS_DEFINITIONS = require('../definitions/plugins'); | const PLUGINS_DEFINITIONS = require('../definitions/plugins'); | ||||||
| const {loadPlugin, parseConfig} = require('./utils'); | const {loadPlugin, parseConfig} = require('./utils'); | ||||||
| 
 | 
 | ||||||
| module.exports = (context, type, pluginOpt, pluginsPath) => { | module.exports = async (context, type, pluginOpt, pluginsPath) => { | ||||||
|   const {stdout, stderr, options, logger} = context; |   const {stdout, stderr, options, logger} = context; | ||||||
|   if (!pluginOpt) { |   if (!pluginOpt) { | ||||||
|     return noop; |     return noop; | ||||||
| @ -13,7 +13,7 @@ module.exports = (context, type, pluginOpt, pluginsPath) => { | |||||||
| 
 | 
 | ||||||
|   const [name, config] = parseConfig(pluginOpt); |   const [name, config] = parseConfig(pluginOpt); | ||||||
|   const pluginName = name.pluginName ? name.pluginName : isFunction(name) ? `[Function: ${name.name}]` : name; |   const pluginName = name.pluginName ? name.pluginName : isFunction(name) ? `[Function: ${name.name}]` : name; | ||||||
|   const plugin = loadPlugin(context, name, pluginsPath); |   const plugin = await loadPlugin(context, name, pluginsPath); | ||||||
| 
 | 
 | ||||||
|   debug(`options for ${pluginName}/${type}: %O`, config); |   debug(`options for ${pluginName}/${type}: %O`, config); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -44,11 +44,14 @@ function validateStep({required}, conf) { | |||||||
|   return conf.length === 0 || validateSteps(conf); |   return conf.length === 0 || validateSteps(conf); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function loadPlugin({cwd}, name, pluginsPath) { | async function loadPlugin({cwd}, name, pluginsPath) { | ||||||
|   const basePath = pluginsPath[name] |   const basePath = pluginsPath[name] | ||||||
|     ? dirname(resolveFrom.silent(__dirname, pluginsPath[name]) || resolveFrom(cwd, pluginsPath[name])) |     ? dirname(resolveFrom.silent(__dirname, pluginsPath[name]) || resolveFrom(cwd, pluginsPath[name])) | ||||||
|     : __dirname; |     : __dirname; | ||||||
|   return isFunction(name) ? name : require(resolveFrom.silent(basePath, name) || resolveFrom(cwd, name)); | 
 | ||||||
|  |   // See https://github.com/mysticatea/eslint-plugin-node/issues/250
 | ||||||
|  |   // eslint-disable-next-line node/no-unsupported-features/es-syntax
 | ||||||
|  |   return isFunction(name) ? name : (await import(resolveFrom.silent(basePath, name) || resolveFrom(cwd, name))).default; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function parseConfig(plugin) { | function parseConfig(plugin) { | ||||||
|  | |||||||
| @ -19,8 +19,8 @@ test.beforeEach((t) => { | |||||||
|   }; |   }; | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| test('Normalize and load plugin from string', (t) => { | test('Normalize and load plugin from string', async (t) => { | ||||||
|   const plugin = normalize( |   const plugin = await normalize( | ||||||
|     {cwd, options: {}, logger: t.context.logger}, |     {cwd, options: {}, logger: t.context.logger}, | ||||||
|     'verifyConditions', |     'verifyConditions', | ||||||
|     './test/fixtures/plugin-noop', |     './test/fixtures/plugin-noop', | ||||||
| @ -32,8 +32,8 @@ test('Normalize and load plugin from string', (t) => { | |||||||
|   t.deepEqual(t.context.success.args[0], ['Loaded plugin "verifyConditions" from "./test/fixtures/plugin-noop"']); |   t.deepEqual(t.context.success.args[0], ['Loaded plugin "verifyConditions" from "./test/fixtures/plugin-noop"']); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| test('Normalize and load plugin from object', (t) => { | test('Normalize and load plugin from object', async (t) => { | ||||||
|   const plugin = normalize( |   const plugin = await normalize( | ||||||
|     {cwd, options: {}, logger: t.context.logger}, |     {cwd, options: {}, logger: t.context.logger}, | ||||||
|     'publish', |     'publish', | ||||||
|     {path: './test/fixtures/plugin-noop'}, |     {path: './test/fixtures/plugin-noop'}, | ||||||
| @ -45,8 +45,8 @@ test('Normalize and load plugin from object', (t) => { | |||||||
|   t.deepEqual(t.context.success.args[0], ['Loaded plugin "publish" from "./test/fixtures/plugin-noop"']); |   t.deepEqual(t.context.success.args[0], ['Loaded plugin "publish" from "./test/fixtures/plugin-noop"']); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| test('Normalize and load plugin from a base file path', (t) => { | test('Normalize and load plugin from a base file path', async (t) => { | ||||||
|   const plugin = normalize({cwd, options: {}, logger: t.context.logger}, 'verifyConditions', './plugin-noop', { |   const plugin = await normalize({cwd, options: {}, logger: t.context.logger}, 'verifyConditions', './plugin-noop', { | ||||||
|     './plugin-noop': './test/fixtures', |     './plugin-noop': './test/fixtures', | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
| @ -58,7 +58,7 @@ test('Normalize and load plugin from a base file path', (t) => { | |||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| test('Wrap plugin in a function that add the "pluginName" to the error"', async (t) => { | test('Wrap plugin in a function that add the "pluginName" to the error"', async (t) => { | ||||||
|   const plugin = normalize({cwd, options: {}, logger: t.context.logger}, 'verifyConditions', './plugin-error', { |   const plugin = await normalize({cwd, options: {}, logger: t.context.logger}, 'verifyConditions', './plugin-error', { | ||||||
|     './plugin-error': './test/fixtures', |     './plugin-error': './test/fixtures', | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
| @ -68,7 +68,7 @@ test('Wrap plugin in a function that add the "pluginName" to the error"', async | |||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| test('Wrap plugin in a function that add the "pluginName" to multiple errors"', async (t) => { | test('Wrap plugin in a function that add the "pluginName" to multiple errors"', async (t) => { | ||||||
|   const plugin = normalize({cwd, options: {}, logger: t.context.logger}, 'verifyConditions', './plugin-errors', { |   const plugin = await normalize({cwd, options: {}, logger: t.context.logger}, 'verifyConditions', './plugin-errors', { | ||||||
|     './plugin-errors': './test/fixtures', |     './plugin-errors': './test/fixtures', | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
| @ -78,16 +78,16 @@ test('Wrap plugin in a function that add the "pluginName" to multiple errors"', | |||||||
|   } |   } | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| test('Normalize and load plugin from function', (t) => { | test('Normalize and load plugin from function', async (t) => { | ||||||
|   const pluginFunction = () => {}; |   const pluginFunction = () => {}; | ||||||
|   const plugin = normalize({cwd, options: {}, logger: t.context.logger}, '', pluginFunction, {}); |   const plugin = await normalize({cwd, options: {}, logger: t.context.logger}, '', pluginFunction, {}); | ||||||
| 
 | 
 | ||||||
|   t.is(plugin.pluginName, '[Function: pluginFunction]'); |   t.is(plugin.pluginName, '[Function: pluginFunction]'); | ||||||
|   t.is(typeof plugin, 'function'); |   t.is(typeof plugin, 'function'); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| test('Normalize and load plugin that retuns multiple functions', (t) => { | test('Normalize and load plugin that retuns multiple functions', async (t) => { | ||||||
|   const plugin = normalize( |   const plugin = await normalize( | ||||||
|     {cwd, options: {}, logger: t.context.logger}, |     {cwd, options: {}, logger: t.context.logger}, | ||||||
|     'verifyConditions', |     'verifyConditions', | ||||||
|     './test/fixtures/multi-plugin', |     './test/fixtures/multi-plugin', | ||||||
| @ -100,7 +100,7 @@ test('Normalize and load plugin that retuns multiple functions', (t) => { | |||||||
| 
 | 
 | ||||||
| test('Wrap "analyzeCommits" plugin in a function that validate the output of the plugin', async (t) => { | test('Wrap "analyzeCommits" plugin in a function that validate the output of the plugin', async (t) => { | ||||||
|   const analyzeCommits = stub().resolves(2); |   const analyzeCommits = stub().resolves(2); | ||||||
|   const plugin = normalize( |   const plugin = await normalize( | ||||||
|     {cwd, options: {}, stderr: t.context.stderr, logger: t.context.logger}, |     {cwd, options: {}, stderr: t.context.stderr, logger: t.context.logger}, | ||||||
|     'analyzeCommits', |     'analyzeCommits', | ||||||
|     analyzeCommits, |     analyzeCommits, | ||||||
| @ -118,7 +118,7 @@ test('Wrap "analyzeCommits" plugin in a function that validate the output of the | |||||||
| 
 | 
 | ||||||
| test('Wrap "generateNotes" plugin in a function that validate the output of the plugin', async (t) => { | test('Wrap "generateNotes" plugin in a function that validate the output of the plugin', async (t) => { | ||||||
|   const generateNotes = stub().resolves(2); |   const generateNotes = stub().resolves(2); | ||||||
|   const plugin = normalize( |   const plugin = await normalize( | ||||||
|     {cwd, options: {}, stderr: t.context.stderr, logger: t.context.logger}, |     {cwd, options: {}, stderr: t.context.stderr, logger: t.context.logger}, | ||||||
|     'generateNotes', |     'generateNotes', | ||||||
|     generateNotes, |     generateNotes, | ||||||
| @ -136,7 +136,7 @@ test('Wrap "generateNotes" plugin in a function that validate the output of the | |||||||
| 
 | 
 | ||||||
| test('Wrap "publish" plugin in a function that validate the output of the plugin', async (t) => { | test('Wrap "publish" plugin in a function that validate the output of the plugin', async (t) => { | ||||||
|   const publish = stub().resolves(2); |   const publish = stub().resolves(2); | ||||||
|   const plugin = normalize( |   const plugin = await normalize( | ||||||
|     {cwd, options: {}, stderr: t.context.stderr, logger: t.context.logger}, |     {cwd, options: {}, stderr: t.context.stderr, logger: t.context.logger}, | ||||||
|     'publish', |     'publish', | ||||||
|     publish, |     publish, | ||||||
| @ -154,7 +154,7 @@ test('Wrap "publish" plugin in a function that validate the output of the plugin | |||||||
| 
 | 
 | ||||||
| test('Wrap "addChannel" plugin in a function that validate the output of the plugin', async (t) => { | test('Wrap "addChannel" plugin in a function that validate the output of the plugin', async (t) => { | ||||||
|   const addChannel = stub().resolves(2); |   const addChannel = stub().resolves(2); | ||||||
|   const plugin = normalize( |   const plugin = await normalize( | ||||||
|     {cwd, options: {}, stderr: t.context.stderr, logger: t.context.logger}, |     {cwd, options: {}, stderr: t.context.stderr, logger: t.context.logger}, | ||||||
|     'addChannel', |     'addChannel', | ||||||
|     addChannel, |     addChannel, | ||||||
| @ -174,7 +174,7 @@ test('Plugin is called with "pluginConfig" (with object definition) and input', | |||||||
|   const pluginFunction = stub().resolves(); |   const pluginFunction = stub().resolves(); | ||||||
|   const pluginConf = {path: pluginFunction, conf: 'confValue'}; |   const pluginConf = {path: pluginFunction, conf: 'confValue'}; | ||||||
|   const options = {global: 'globalValue'}; |   const options = {global: 'globalValue'}; | ||||||
|   const plugin = normalize({cwd, options, logger: t.context.logger}, '', pluginConf, {}); |   const plugin = await normalize({cwd, options, logger: t.context.logger}, '', pluginConf, {}); | ||||||
|   await plugin({options: {}, param: 'param'}); |   await plugin({options: {}, param: 'param'}); | ||||||
| 
 | 
 | ||||||
|   t.true( |   t.true( | ||||||
| @ -189,7 +189,7 @@ test('Plugin is called with "pluginConfig" (with array definition) and input', a | |||||||
|   const pluginFunction = stub().resolves(); |   const pluginFunction = stub().resolves(); | ||||||
|   const pluginConf = [pluginFunction, {conf: 'confValue'}]; |   const pluginConf = [pluginFunction, {conf: 'confValue'}]; | ||||||
|   const options = {global: 'globalValue'}; |   const options = {global: 'globalValue'}; | ||||||
|   const plugin = normalize({cwd, options, logger: t.context.logger}, '', pluginConf, {}); |   const plugin = await normalize({cwd, options, logger: t.context.logger}, '', pluginConf, {}); | ||||||
|   await plugin({options: {}, param: 'param'}); |   await plugin({options: {}, param: 'param'}); | ||||||
| 
 | 
 | ||||||
|   t.true( |   t.true( | ||||||
| @ -206,7 +206,7 @@ test('Prevent plugins to modify "pluginConfig"', async (t) => { | |||||||
|   }); |   }); | ||||||
|   const pluginConf = {path: pluginFunction, conf: {subConf: 'originalConf'}}; |   const pluginConf = {path: pluginFunction, conf: {subConf: 'originalConf'}}; | ||||||
|   const options = {globalConf: {globalSubConf: 'originalGlobalConf'}}; |   const options = {globalConf: {globalSubConf: 'originalGlobalConf'}}; | ||||||
|   const plugin = normalize({cwd, options, logger: t.context.logger}, '', pluginConf, {}); |   const plugin = await normalize({cwd, options, logger: t.context.logger}, '', pluginConf, {}); | ||||||
|   await plugin({options: {}}); |   await plugin({options: {}}); | ||||||
| 
 | 
 | ||||||
|   t.is(pluginConf.conf.subConf, 'originalConf'); |   t.is(pluginConf.conf.subConf, 'originalConf'); | ||||||
| @ -218,21 +218,21 @@ test('Prevent plugins to modify its input', async (t) => { | |||||||
|     options.param.subParam = 'otherParam'; |     options.param.subParam = 'otherParam'; | ||||||
|   }); |   }); | ||||||
|   const input = {param: {subParam: 'originalSubParam'}, options: {}}; |   const input = {param: {subParam: 'originalSubParam'}, options: {}}; | ||||||
|   const plugin = normalize({cwd, options: {}, logger: t.context.logger}, '', pluginFunction, {}); |   const plugin = await normalize({cwd, options: {}, logger: t.context.logger}, '', pluginFunction, {}); | ||||||
|   await plugin(input); |   await plugin(input); | ||||||
| 
 | 
 | ||||||
|   t.is(input.param.subParam, 'originalSubParam'); |   t.is(input.param.subParam, 'originalSubParam'); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| test('Return noop if the plugin is not defined', (t) => { | test('Return noop if the plugin is not defined', async (t) => { | ||||||
|   const plugin = normalize({cwd, options: {}, logger: t.context.logger}); |   const plugin = await normalize({cwd, options: {}, logger: t.context.logger}); | ||||||
| 
 | 
 | ||||||
|   t.is(plugin, noop); |   t.is(plugin, noop); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| test('Always pass a defined "pluginConfig" for plugin defined with string', async (t) => { | test('Always pass a defined "pluginConfig" for plugin defined with string', async (t) => { | ||||||
|   // Call the normalize function with the path of a plugin that returns its config
 |   // Call the normalize function with the path of a plugin that returns its config
 | ||||||
|   const plugin = normalize( |   const plugin = await normalize( | ||||||
|     {cwd, options: {}, logger: t.context.logger}, |     {cwd, options: {}, logger: t.context.logger}, | ||||||
|     '', |     '', | ||||||
|     './test/fixtures/plugin-result-config', |     './test/fixtures/plugin-result-config', | ||||||
| @ -245,7 +245,7 @@ test('Always pass a defined "pluginConfig" for plugin defined with string', asyn | |||||||
| 
 | 
 | ||||||
| test('Always pass a defined "pluginConfig" for plugin defined with path', async (t) => { | test('Always pass a defined "pluginConfig" for plugin defined with path', async (t) => { | ||||||
|   // Call the normalize function with the path of a plugin that returns its config
 |   // Call the normalize function with the path of a plugin that returns its config
 | ||||||
|   const plugin = normalize( |   const plugin = await normalize( | ||||||
|     {cwd, options: {}, logger: t.context.logger}, |     {cwd, options: {}, logger: t.context.logger}, | ||||||
|     '', |     '', | ||||||
|     {path: './test/fixtures/plugin-result-config'}, |     {path: './test/fixtures/plugin-result-config'}, | ||||||
| @ -256,8 +256,8 @@ test('Always pass a defined "pluginConfig" for plugin defined with path', async | |||||||
|   t.deepEqual(pluginResult.pluginConfig, {}); |   t.deepEqual(pluginResult.pluginConfig, {}); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| test('Throws an error if the plugin return an object without the expected plugin function', (t) => { | test('Throws an error if the plugin return an object without the expected plugin function', async (t) => { | ||||||
|   const error = t.throws(() => |   const error = await t.throwsAsync(() => | ||||||
|     normalize({cwd, options: {}, logger: t.context.logger}, 'inexistantPlugin', './test/fixtures/multi-plugin', {}) |     normalize({cwd, options: {}, logger: t.context.logger}, 'inexistantPlugin', './test/fixtures/multi-plugin', {}) | ||||||
|   ); |   ); | ||||||
| 
 | 
 | ||||||
| @ -267,10 +267,13 @@ test('Throws an error if the plugin return an object without the expected plugin | |||||||
|   t.truthy(error.details); |   t.truthy(error.details); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| test('Throws an error if the plugin is not found', (t) => { | test('Throws an error if the plugin is not found', async (t) => { | ||||||
|   t.throws(() => normalize({cwd, options: {}, logger: t.context.logger}, 'inexistantPlugin', 'non-existing-path', {}), { |   await t.throwsAsync( | ||||||
|  |     () => normalize({cwd, options: {}, logger: t.context.logger}, 'inexistantPlugin', 'non-existing-path', {}), | ||||||
|  |     { | ||||||
|       message: /Cannot find module 'non-existing-path'/, |       message: /Cannot find module 'non-existing-path'/, | ||||||
|       code: 'MODULE_NOT_FOUND', |       code: 'MODULE_NOT_FOUND', | ||||||
|       instanceOf: Error, |       instanceOf: Error, | ||||||
|   }); |     } | ||||||
|  |   ); | ||||||
| }); | }); | ||||||
|  | |||||||
| @ -15,8 +15,8 @@ test.beforeEach((t) => { | |||||||
|   t.context.logger = {log: t.context.log, success: t.context.success, scope: () => t.context.logger}; |   t.context.logger = {log: t.context.log, success: t.context.success, scope: () => t.context.logger}; | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| test('Export default plugins', (t) => { | test('Export default plugins', async (t) => { | ||||||
|   const plugins = getPlugins({cwd, options: {}, logger: t.context.logger}, {}); |   const plugins = await getPlugins({cwd, options: {}, logger: t.context.logger}, {}); | ||||||
| 
 | 
 | ||||||
|   // Verify the module returns a function for each plugin
 |   // Verify the module returns a function for each plugin
 | ||||||
|   t.is(typeof plugins.verifyConditions, 'function'); |   t.is(typeof plugins.verifyConditions, 'function'); | ||||||
| @ -29,8 +29,8 @@ test('Export default plugins', (t) => { | |||||||
|   t.is(typeof plugins.fail, 'function'); |   t.is(typeof plugins.fail, 'function'); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| test('Export plugins based on steps config', (t) => { | test('Export plugins based on steps config', async (t) => { | ||||||
|   const plugins = getPlugins( |   const plugins = await getPlugins( | ||||||
|     { |     { | ||||||
|       cwd, |       cwd, | ||||||
|       logger: t.context.logger, |       logger: t.context.logger, | ||||||
| @ -58,11 +58,10 @@ test('Export plugins based on steps config', (t) => { | |||||||
| test('Export plugins based on "plugins" config (array)', async (t) => { | test('Export plugins based on "plugins" config (array)', async (t) => { | ||||||
|   const plugin1 = {verifyConditions: stub(), publish: stub()}; |   const plugin1 = {verifyConditions: stub(), publish: stub()}; | ||||||
|   const plugin2 = {verifyConditions: stub(), verifyRelease: stub()}; |   const plugin2 = {verifyConditions: stub(), verifyRelease: stub()}; | ||||||
|   const plugins = getPlugins( |   const plugins = await getPlugins( | ||||||
|     {cwd, logger: t.context.logger, options: {plugins: [plugin1, [plugin2, {}]], verifyRelease: () => {}}}, |     {cwd, logger: t.context.logger, options: {plugins: [plugin1, [plugin2, {}]], verifyRelease: () => {}}}, | ||||||
|     {} |     {} | ||||||
|   ); |   ); | ||||||
| 
 |  | ||||||
|   await plugins.verifyConditions({options: {}}); |   await plugins.verifyConditions({options: {}}); | ||||||
|   t.true(plugin1.verifyConditions.calledOnce); |   t.true(plugin1.verifyConditions.calledOnce); | ||||||
|   t.true(plugin2.verifyConditions.calledOnce); |   t.true(plugin2.verifyConditions.calledOnce); | ||||||
| @ -86,7 +85,7 @@ test('Export plugins based on "plugins" config (array)', async (t) => { | |||||||
| 
 | 
 | ||||||
| test('Export plugins based on "plugins" config (single definition)', async (t) => { | test('Export plugins based on "plugins" config (single definition)', async (t) => { | ||||||
|   const plugin1 = {verifyConditions: stub(), publish: stub()}; |   const plugin1 = {verifyConditions: stub(), publish: stub()}; | ||||||
|   const plugins = getPlugins({cwd, logger: t.context.logger, options: {plugins: plugin1}}, {}); |   const plugins = await getPlugins({cwd, logger: t.context.logger, options: {plugins: plugin1}}, {}); | ||||||
| 
 | 
 | ||||||
|   await plugins.verifyConditions({options: {}}); |   await plugins.verifyConditions({options: {}}); | ||||||
|   t.true(plugin1.verifyConditions.calledOnce); |   t.true(plugin1.verifyConditions.calledOnce); | ||||||
| @ -109,7 +108,7 @@ test('Merge global options, "plugins" options and step options', async (t) => { | |||||||
|   const plugin1 = [{verifyConditions: stub(), publish: stub()}, {pluginOpt1: 'plugin1'}]; |   const plugin1 = [{verifyConditions: stub(), publish: stub()}, {pluginOpt1: 'plugin1'}]; | ||||||
|   const plugin2 = [{verifyConditions: stub()}, {pluginOpt2: 'plugin2'}]; |   const plugin2 = [{verifyConditions: stub()}, {pluginOpt2: 'plugin2'}]; | ||||||
|   const plugin3 = [stub(), {pluginOpt3: 'plugin3'}]; |   const plugin3 = [stub(), {pluginOpt3: 'plugin3'}]; | ||||||
|   const plugins = getPlugins( |   const plugins = await getPlugins( | ||||||
|     { |     { | ||||||
|       cwd, |       cwd, | ||||||
|       logger: t.context.logger, |       logger: t.context.logger, | ||||||
| @ -129,9 +128,9 @@ test('Merge global options, "plugins" options and step options', async (t) => { | |||||||
|   t.deepEqual(plugin3[0].args[0][0], {globalOpt: 'global', pluginOpt3: 'plugin3'}); |   t.deepEqual(plugin3[0].args[0][0], {globalOpt: 'global', pluginOpt3: 'plugin3'}); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| test('Unknown steps of plugins configured in "plugins" are ignored', (t) => { | test('Unknown steps of plugins configured in "plugins" are ignored', async (t) => { | ||||||
|   const plugin1 = {verifyConditions: () => {}, unknown: () => {}}; |   const plugin1 = {verifyConditions: () => {}, unknown: () => {}}; | ||||||
|   const plugins = getPlugins({cwd, logger: t.context.logger, options: {plugins: [plugin1]}}, {}); |   const plugins = await getPlugins({cwd, logger: t.context.logger, options: {plugins: [plugin1]}}, {}); | ||||||
| 
 | 
 | ||||||
|   t.is(typeof plugins.verifyConditions, 'function'); |   t.is(typeof plugins.verifyConditions, 'function'); | ||||||
|   t.is(plugins.unknown, undefined); |   t.is(plugins.unknown, undefined); | ||||||
| @ -145,7 +144,7 @@ test('Export plugins loaded from the dependency of a shareable config module', a | |||||||
|   ); |   ); | ||||||
|   await outputFile(path.resolve(cwd, 'node_modules/shareable-config/index.js'), ''); |   await outputFile(path.resolve(cwd, 'node_modules/shareable-config/index.js'), ''); | ||||||
| 
 | 
 | ||||||
|   const plugins = getPlugins( |   const plugins = await getPlugins( | ||||||
|     { |     { | ||||||
|       cwd, |       cwd, | ||||||
|       logger: t.context.logger, |       logger: t.context.logger, | ||||||
| @ -175,7 +174,7 @@ test('Export plugins loaded from the dependency of a shareable config file', asy | |||||||
|   await copy('./test/fixtures/plugin-noop.js', path.resolve(cwd, 'plugin/plugin-noop.js')); |   await copy('./test/fixtures/plugin-noop.js', path.resolve(cwd, 'plugin/plugin-noop.js')); | ||||||
|   await outputFile(path.resolve(cwd, 'shareable-config.js'), ''); |   await outputFile(path.resolve(cwd, 'shareable-config.js'), ''); | ||||||
| 
 | 
 | ||||||
|   const plugins = getPlugins( |   const plugins = await getPlugins( | ||||||
|     { |     { | ||||||
|       cwd, |       cwd, | ||||||
|       logger: t.context.logger, |       logger: t.context.logger, | ||||||
| @ -200,14 +199,14 @@ test('Export plugins loaded from the dependency of a shareable config file', asy | |||||||
|   t.is(typeof plugins.fail, 'function'); |   t.is(typeof plugins.fail, 'function'); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| test('Use default when only options are passed for a single plugin', (t) => { | test('Use default when only options are passed for a single plugin', async (t) => { | ||||||
|   const analyzeCommits = {}; |   const analyzeCommits = {}; | ||||||
|   const generateNotes = {}; |   const generateNotes = {}; | ||||||
|   const publish = {}; |   const publish = {}; | ||||||
|   const success = () => {}; |   const success = () => {}; | ||||||
|   const fail = [() => {}]; |   const fail = [() => {}]; | ||||||
| 
 | 
 | ||||||
|   const plugins = getPlugins( |   const plugins = await getPlugins( | ||||||
|     { |     { | ||||||
|       cwd, |       cwd, | ||||||
|       logger: t.context.logger, |       logger: t.context.logger, | ||||||
| @ -235,7 +234,7 @@ test('Use default when only options are passed for a single plugin', (t) => { | |||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| test('Merge global options with plugin options', async (t) => { | test('Merge global options with plugin options', async (t) => { | ||||||
|   const plugins = getPlugins( |   const plugins = await getPlugins( | ||||||
|     { |     { | ||||||
|       cwd, |       cwd, | ||||||
|       logger: t.context.logger, |       logger: t.context.logger, | ||||||
| @ -253,9 +252,9 @@ test('Merge global options with plugin options', async (t) => { | |||||||
|   t.deepEqual(result.pluginConfig, {localOpt: 'local', globalOpt: 'global', otherOpt: 'locally-defined'}); |   t.deepEqual(result.pluginConfig, {localOpt: 'local', globalOpt: 'global', otherOpt: 'locally-defined'}); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| test('Throw an error for each invalid plugin configuration', (t) => { | test('Throw an error for each invalid plugin configuration', async (t) => { | ||||||
|   const errors = [ |   const errors = [ | ||||||
|     ...t.throws(() => |     ...(await t.throwsAsync(() => | ||||||
|       getPlugins( |       getPlugins( | ||||||
|         { |         { | ||||||
|           cwd, |           cwd, | ||||||
| @ -270,7 +269,7 @@ test('Throw an error for each invalid plugin configuration', (t) => { | |||||||
|         }, |         }, | ||||||
|         {} |         {} | ||||||
|       ) |       ) | ||||||
|     ), |     )), | ||||||
|   ]; |   ]; | ||||||
| 
 | 
 | ||||||
|   t.is(errors[0].name, 'SemanticReleaseError'); |   t.is(errors[0].name, 'SemanticReleaseError'); | ||||||
| @ -283,9 +282,9 @@ test('Throw an error for each invalid plugin configuration', (t) => { | |||||||
|   t.is(errors[3].code, 'EPLUGINCONF'); |   t.is(errors[3].code, 'EPLUGINCONF'); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| test('Throw EPLUGINSCONF error if the "plugins" option contains an old plugin definition (returns a function)', (t) => { | test('Throw EPLUGINSCONF error if the "plugins" option contains an old plugin definition (returns a function)', async (t) => { | ||||||
|   const errors = [ |   const errors = [ | ||||||
|     ...t.throws(() => |     ...(await t.throwsAsync(() => | ||||||
|       getPlugins( |       getPlugins( | ||||||
|         { |         { | ||||||
|           cwd, |           cwd, | ||||||
| @ -294,7 +293,7 @@ test('Throw EPLUGINSCONF error if the "plugins" option contains an old plugin de | |||||||
|         }, |         }, | ||||||
|         {} |         {} | ||||||
|       ) |       ) | ||||||
|     ), |     )), | ||||||
|   ]; |   ]; | ||||||
| 
 | 
 | ||||||
|   t.is(errors[0].name, 'SemanticReleaseError'); |   t.is(errors[0].name, 'SemanticReleaseError'); | ||||||
| @ -303,11 +302,11 @@ test('Throw EPLUGINSCONF error if the "plugins" option contains an old plugin de | |||||||
|   t.is(errors[1].code, 'EPLUGINSCONF'); |   t.is(errors[1].code, 'EPLUGINSCONF'); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| test('Throw EPLUGINSCONF error for each invalid definition if the "plugins" option', (t) => { | test('Throw EPLUGINSCONF error for each invalid definition if the "plugins" option', async (t) => { | ||||||
|   const errors = [ |   const errors = [ | ||||||
|     ...t.throws(() => |     ...(await t.throwsAsync(() => | ||||||
|       getPlugins({cwd, logger: t.context.logger, options: {plugins: [1, {path: 1}, [() => {}, {}, {}]]}}, {}) |       getPlugins({cwd, logger: t.context.logger, options: {plugins: [1, {path: 1}, [() => {}, {}, {}]]}}, {}) | ||||||
|     ), |     )), | ||||||
|   ]; |   ]; | ||||||
| 
 | 
 | ||||||
|   t.is(errors[0].name, 'SemanticReleaseError'); |   t.is(errors[0].name, 'SemanticReleaseError'); | ||||||
|  | |||||||
| @ -189,17 +189,17 @@ test('validateStep: required plugin configuration', (t) => { | |||||||
|   ); |   ); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| test('loadPlugin', (t) => { | test('loadPlugin', async (t) => { | ||||||
|   const cwd = process.cwd(); |   const cwd = process.cwd(); | ||||||
|   const func = () => {}; |   const func = () => {}; | ||||||
| 
 | 
 | ||||||
|   t.is(require('../fixtures/plugin-noop'), loadPlugin({cwd: './test/fixtures'}, './plugin-noop', {}), 'From cwd'); |   t.is(require('../fixtures/plugin-noop'), await loadPlugin({cwd: './test/fixtures'}, './plugin-noop', {}), 'From cwd'); | ||||||
|   t.is( |   t.is( | ||||||
|     require('../fixtures/plugin-noop'), |     require('../fixtures/plugin-noop'), | ||||||
|     loadPlugin({cwd}, './plugin-noop', {'./plugin-noop': './test/fixtures'}), |     await loadPlugin({cwd}, './plugin-noop', {'./plugin-noop': './test/fixtures'}), | ||||||
|     'From a shareable config context' |     'From a shareable config context' | ||||||
|   ); |   ); | ||||||
|   t.is(func, loadPlugin({cwd}, func, {}), 'Defined as a function'); |   t.is(func, await loadPlugin({cwd}, func, {}), 'Defined as a function'); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| test('parseConfig', (t) => { | test('parseConfig', (t) => { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user