fix(core): fail fast if plugin has no name (#10239)

This commit is contained in:
Sébastien Lorber 2024-06-20 19:15:36 +02:00 committed by GitHub
parent 2eecd70700
commit 97630b438e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 74 additions and 40 deletions

View file

@ -0,0 +1,19 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
module.exports = {
title: 'My Site',
tagline: 'The tagline of my site',
url: 'https://your-docusaurus-site.example.com',
baseUrl: '/',
favicon: 'img/favicon.ico',
plugins: [
function (context, options) {
return {noname: 'on-purpose'};
},
],
};

View file

@ -1,29 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`initPlugins throws user-friendly error message for plugins with bad values 1`] = `
" => Bad Docusaurus plugin value plugins[0].
Example valid plugin config:
{
plugins: [
["@docusaurus/plugin-content-docs",options],
"./myPlugin",
["./myPlugin",{someOption: 42}],
function myPlugin() { },
[function myPlugin() { },options]
],
};
=> Bad Docusaurus plugin value plugins[1].
Example valid plugin config:
{
plugins: [
["@docusaurus/plugin-content-docs",options],
"./myPlugin",
["./myPlugin",{someOption: 42}],
function myPlugin() { },
[function myPlugin() { },options]
],
};
"
`;

View file

@ -10,17 +10,20 @@ import path from 'path';
import {loadContext, type LoadContextParams} from '../../site';
import {initPlugins} from '../init';
async function loadSite(
fixtureName: string,
options: Omit<LoadContextParams, 'siteDir'> = {},
) {
const siteDir = path.join(__dirname, '__fixtures__', fixtureName);
const context = await loadContext({...options, siteDir});
const plugins = await initPlugins(context);
return {siteDir, context, plugins};
}
describe('initPlugins', () => {
async function loadSite(options: Omit<LoadContextParams, 'siteDir'> = {}) {
const siteDir = path.join(__dirname, '__fixtures__', 'site-with-plugin');
const context = await loadContext({...options, siteDir});
const plugins = await initPlugins(context);
return {siteDir, context, plugins};
}
it('parses plugins correctly and loads them in correct order', async () => {
const {context, plugins} = await loadSite();
const {context, plugins} = await loadSite('site-with-plugin');
expect(context.siteConfig.plugins).toHaveLength(6);
expect(plugins).toHaveLength(10);
@ -45,7 +48,41 @@ describe('initPlugins', () => {
it('throws user-friendly error message for plugins with bad values', async () => {
await expect(() =>
loadSite({config: 'badPlugins.docusaurus.config.js'}),
).rejects.toThrowErrorMatchingSnapshot();
loadSite('site-with-plugin', {config: 'badPlugins.docusaurus.config.js'}),
).rejects.toThrowErrorMatchingInlineSnapshot(`
" => Bad Docusaurus plugin value plugins[0].
Example valid plugin config:
{
plugins: [
["@docusaurus/plugin-content-docs",options],
"./myPlugin",
["./myPlugin",{someOption: 42}],
function myPlugin() { },
[function myPlugin() { },options]
],
};
=> Bad Docusaurus plugin value plugins[1].
Example valid plugin config:
{
plugins: [
["@docusaurus/plugin-content-docs",options],
"./myPlugin",
["./myPlugin",{someOption: 42}],
function myPlugin() { },
[function myPlugin() { },options]
],
};
"
`);
});
it('throws user-friendly error message for plugins with no name', async () => {
await expect(() => loadSite('site-with-unnamed-plugin')).rejects
.toThrowErrorMatchingInlineSnapshot(`
"A Docusaurus plugin is missing a 'name' property.
Note that even inline/anonymous plugin functions require a 'name' property."
`);
});
});

View file

@ -125,6 +125,13 @@ export async function initPlugins(
pluginOptions,
);
if (!pluginInstance.name) {
throw new Error(
`A Docusaurus plugin is missing a 'name' property.
Note that even inline/anonymous plugin functions require a 'name' property.`,
);
}
return {
...pluginInstance,
options: pluginOptions,