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