mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-23 22:17:00 +02:00
feat(v2): blog + docs multi-instance plugins (#3204)
* stable createData namespacing + second-blog dogfooding * Docs: support multi-instance + make community docs a separate instance * tests: add 2nd docs instance to versioned site * fix docs version cli tests * fix docs versioning cli * typo * team: add link to my site * better extendCli integration * fix metadata tests * tests for versioned site with second docs instance * move some validation code to utils-validation * fix missing dependency * fix bad compiled output due to importing constants in ./client folder * make docs tests easier to maintain * refactors * prevent lodash imports in client bundle * redirect old community docs to new urls
This commit is contained in:
parent
e944f35640
commit
59f705ee66
67 changed files with 2025 additions and 2059 deletions
|
@ -0,0 +1 @@
|
|||
Team current version
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"community": ["team"]
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
Team 1.0.0
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"version-1.0.0/community": ["version-1.0.0/team"]
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
["1.0.0"]
|
File diff suppressed because it is too large
Load diff
|
@ -77,3 +77,14 @@ Object {
|
|||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`docsVersion second docs instance versioning 1`] = `
|
||||
Object {
|
||||
"version-2.0.0/community": Array [
|
||||
Object {
|
||||
"id": "version-2.0.0/team",
|
||||
"type": "doc",
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -7,18 +7,19 @@
|
|||
|
||||
import path from 'path';
|
||||
import loadEnv from '../env';
|
||||
import {DEFAULT_PLUGIN_ID} from '@docusaurus/core/lib/constants';
|
||||
|
||||
describe('loadEnv', () => {
|
||||
test('website with versioning disabled', () => {
|
||||
const siteDir = path.join(__dirname, '__fixtures__', 'simple-site');
|
||||
const env = loadEnv(siteDir);
|
||||
const env = loadEnv(siteDir, DEFAULT_PLUGIN_ID);
|
||||
expect(env.versioning.enabled).toBe(false);
|
||||
expect(env.versioning.versions).toStrictEqual([]);
|
||||
});
|
||||
|
||||
test('website with versioning enabled', () => {
|
||||
const siteDir = path.join(__dirname, '__fixtures__', 'versioned-site');
|
||||
const env = loadEnv(siteDir);
|
||||
const env = loadEnv(siteDir, DEFAULT_PLUGIN_ID);
|
||||
expect(env.versioning.enabled).toBe(true);
|
||||
expect(env.versioning.latestVersion).toBe('1.0.1');
|
||||
expect(env.versioning.versions).toStrictEqual([
|
||||
|
@ -28,9 +29,17 @@ describe('loadEnv', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('website with versioning enabled, 2nd docs plugin instance', () => {
|
||||
const siteDir = path.join(__dirname, '__fixtures__', 'versioned-site');
|
||||
const env = loadEnv(siteDir, 'community');
|
||||
expect(env.versioning.enabled).toBe(true);
|
||||
expect(env.versioning.latestVersion).toBe('1.0.0');
|
||||
expect(env.versioning.versions).toStrictEqual(['1.0.0']);
|
||||
});
|
||||
|
||||
test('website with versioning but disabled', () => {
|
||||
const siteDir = path.join(__dirname, '__fixtures__', 'versioned-site');
|
||||
const env = loadEnv(siteDir, {disableVersioning: true});
|
||||
const env = loadEnv(siteDir, DEFAULT_PLUGIN_ID, {disableVersioning: true});
|
||||
expect(env.versioning.enabled).toBe(false);
|
||||
expect(env.versioning.versions).toStrictEqual([]);
|
||||
});
|
||||
|
@ -42,7 +51,7 @@ describe('loadEnv', () => {
|
|||
invalid: 'json',
|
||||
};
|
||||
});
|
||||
const env = loadEnv(siteDir);
|
||||
const env = loadEnv(siteDir, DEFAULT_PLUGIN_ID);
|
||||
expect(env.versioning.enabled).toBe(false);
|
||||
mock.mockRestore();
|
||||
});
|
||||
|
|
|
@ -12,35 +12,65 @@ import commander from 'commander';
|
|||
import fs from 'fs-extra';
|
||||
import pluginContentDocs from '../index';
|
||||
import loadEnv from '../env';
|
||||
import normalizePluginOptions from './pluginOptionSchema.test';
|
||||
import {loadContext} from '@docusaurus/core/src/server/index';
|
||||
import {applyConfigureWebpack} from '@docusaurus/core/src/webpack/utils';
|
||||
import {RouteConfig} from '@docusaurus/types';
|
||||
import {posixPath} from '@docusaurus/utils';
|
||||
import {sortConfig} from '@docusaurus/core/src/server/plugins';
|
||||
import {DEFAULT_PLUGIN_ID} from '@docusaurus/core/lib/constants';
|
||||
|
||||
import * as version from '../version';
|
||||
import {PluginOptionSchema} from '../pluginOptionSchema';
|
||||
import {normalizePluginOptions} from '@docusaurus/utils-validation';
|
||||
|
||||
const createFakeActions = (
|
||||
routeConfigs: RouteConfig[],
|
||||
contentDir,
|
||||
dataContainer?,
|
||||
globalDataContainer?,
|
||||
) => {
|
||||
return {
|
||||
const createFakeActions = (contentDir: string) => {
|
||||
const routeConfigs: RouteConfig[] = [];
|
||||
const dataContainer: any = {};
|
||||
const globalDataContainer: any = {};
|
||||
|
||||
const actions = {
|
||||
addRoute: (config: RouteConfig) => {
|
||||
routeConfigs.push(config);
|
||||
},
|
||||
createData: async (name, content) => {
|
||||
if (dataContainer) {
|
||||
dataContainer[name] = content;
|
||||
}
|
||||
createData: async (name: string, content: unknown) => {
|
||||
dataContainer[name] = content;
|
||||
return path.join(contentDir, name);
|
||||
},
|
||||
setGlobalData: (data) => {
|
||||
setGlobalData: (data: any) => {
|
||||
globalDataContainer.pluginName = {pluginId: data};
|
||||
},
|
||||
};
|
||||
|
||||
// Extra fns useful for tests!
|
||||
const utils = {
|
||||
getGlobalData: () => globalDataContainer,
|
||||
getRouteConfigs: () => routeConfigs,
|
||||
// query by prefix, because files have a hash at the end
|
||||
// so it's not convenient to query by full filename
|
||||
getCreatedDataByPrefix: (prefix: string) => {
|
||||
const entry = Object.entries(dataContainer).find(([key]) =>
|
||||
key.startsWith(prefix),
|
||||
);
|
||||
if (!entry) {
|
||||
throw new Error(`No entry found for prefix=${prefix}`);
|
||||
}
|
||||
return JSON.parse(entry[1] as string);
|
||||
},
|
||||
|
||||
expectSnapshot: () => {
|
||||
// Sort the route config like in src/server/plugins/index.ts for consistent snapshot ordering
|
||||
sortConfig(routeConfigs);
|
||||
expect(routeConfigs).not.toEqual([]);
|
||||
expect(routeConfigs).toMatchSnapshot('route config');
|
||||
expect(dataContainer).toMatchSnapshot('data');
|
||||
expect(globalDataContainer).toMatchSnapshot('global data');
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
actions,
|
||||
utils,
|
||||
};
|
||||
};
|
||||
|
||||
test('site with wrong sidebar file', async () => {
|
||||
|
@ -49,7 +79,7 @@ test('site with wrong sidebar file', async () => {
|
|||
const sidebarPath = path.join(siteDir, 'wrong-sidebars.json');
|
||||
const plugin = pluginContentDocs(
|
||||
context,
|
||||
normalizePluginOptions({
|
||||
normalizePluginOptions(PluginOptionSchema, {
|
||||
sidebarPath,
|
||||
}),
|
||||
);
|
||||
|
@ -62,28 +92,30 @@ describe('empty/no docs website', () => {
|
|||
|
||||
test('no files in docs folder', async () => {
|
||||
await fs.ensureDir(path.join(siteDir, 'docs'));
|
||||
const plugin = pluginContentDocs(context, normalizePluginOptions({}));
|
||||
const plugin = pluginContentDocs(
|
||||
context,
|
||||
normalizePluginOptions(PluginOptionSchema, {}),
|
||||
);
|
||||
const content = await plugin.loadContent();
|
||||
const {docsMetadata, docsSidebars} = content;
|
||||
expect(docsMetadata).toMatchInlineSnapshot(`Object {}`);
|
||||
expect(docsSidebars).toMatchInlineSnapshot(`Object {}`);
|
||||
|
||||
const routeConfigs = [];
|
||||
const pluginContentDir = path.join(context.generatedFilesDir, plugin.name);
|
||||
const actions = createFakeActions(routeConfigs, pluginContentDir);
|
||||
const {actions, utils} = createFakeActions(pluginContentDir);
|
||||
|
||||
await plugin.contentLoaded({
|
||||
content,
|
||||
actions,
|
||||
});
|
||||
|
||||
expect(routeConfigs).toEqual([]);
|
||||
expect(utils.getRouteConfigs()).toEqual([]);
|
||||
});
|
||||
|
||||
test('docs folder does not exist', async () => {
|
||||
const plugin = pluginContentDocs(
|
||||
context,
|
||||
normalizePluginOptions({
|
||||
normalizePluginOptions(PluginOptionSchema, {
|
||||
path: '/path/does/not/exist/',
|
||||
}),
|
||||
);
|
||||
|
@ -99,7 +131,7 @@ describe('simple website', () => {
|
|||
const pluginPath = 'docs';
|
||||
const plugin = pluginContentDocs(
|
||||
context,
|
||||
normalizePluginOptions({
|
||||
normalizePluginOptions(PluginOptionSchema, {
|
||||
path: pluginPath,
|
||||
sidebarPath,
|
||||
homePageId: 'hello',
|
||||
|
@ -112,7 +144,7 @@ describe('simple website', () => {
|
|||
const cli = new commander.Command();
|
||||
plugin.extendCli(cli);
|
||||
cli.parse(['node', 'test', 'docs:version', '1.0.0']);
|
||||
expect(mock).toHaveBeenCalledWith('1.0.0', siteDir, {
|
||||
expect(mock).toHaveBeenCalledWith('1.0.0', siteDir, DEFAULT_PLUGIN_ID, {
|
||||
path: pluginPath,
|
||||
sidebarPath,
|
||||
});
|
||||
|
@ -200,15 +232,7 @@ describe('simple website', () => {
|
|||
|
||||
expect(docsSidebars).toMatchSnapshot();
|
||||
|
||||
const routeConfigs = [];
|
||||
const dataContainer = {};
|
||||
const globalDataContainer = {};
|
||||
const actions = createFakeActions(
|
||||
routeConfigs,
|
||||
pluginContentDir,
|
||||
dataContainer,
|
||||
globalDataContainer,
|
||||
);
|
||||
const {actions, utils} = createFakeActions(pluginContentDir);
|
||||
|
||||
await plugin.contentLoaded({
|
||||
content,
|
||||
|
@ -216,16 +240,12 @@ describe('simple website', () => {
|
|||
});
|
||||
|
||||
// There is only one nested docs route for simple site
|
||||
const baseMetadata = JSON.parse(dataContainer['docs-route-ff2.json']);
|
||||
const baseMetadata = utils.getCreatedDataByPrefix('docs-route-');
|
||||
expect(baseMetadata.docsSidebars).toEqual(docsSidebars);
|
||||
expect(baseMetadata.permalinkToSidebar).toEqual(permalinkToSidebar);
|
||||
|
||||
// Sort the route config like in src/server/plugins/index.ts for consistent snapshot ordering
|
||||
sortConfig(routeConfigs);
|
||||
|
||||
expect(routeConfigs).not.toEqual([]);
|
||||
expect(routeConfigs).toMatchSnapshot();
|
||||
expect(globalDataContainer).toMatchSnapshot();
|
||||
utils.expectSnapshot();
|
||||
expect(utils.getGlobalData()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -236,22 +256,26 @@ describe('versioned website', () => {
|
|||
const routeBasePath = 'docs';
|
||||
const plugin = pluginContentDocs(
|
||||
context,
|
||||
normalizePluginOptions({
|
||||
normalizePluginOptions(PluginOptionSchema, {
|
||||
routeBasePath,
|
||||
sidebarPath,
|
||||
homePageId: 'hello',
|
||||
}),
|
||||
);
|
||||
const env = loadEnv(siteDir);
|
||||
const env = loadEnv(siteDir, DEFAULT_PLUGIN_ID);
|
||||
const {docsDir: versionedDir} = env.versioning;
|
||||
const pluginContentDir = path.join(context.generatedFilesDir, plugin.name);
|
||||
|
||||
test('isVersioned', () => {
|
||||
expect(env.versioning.enabled).toEqual(true);
|
||||
});
|
||||
|
||||
test('extendCli - docsVersion', () => {
|
||||
const mock = jest.spyOn(version, 'docsVersion').mockImplementation();
|
||||
const cli = new commander.Command();
|
||||
plugin.extendCli(cli);
|
||||
cli.parse(['node', 'test', 'docs:version', '2.0.0']);
|
||||
expect(mock).toHaveBeenCalledWith('2.0.0', siteDir, {
|
||||
expect(mock).toHaveBeenCalledWith('2.0.0', siteDir, DEFAULT_PLUGIN_ID, {
|
||||
path: routeBasePath,
|
||||
sidebarPath,
|
||||
});
|
||||
|
@ -401,23 +425,15 @@ describe('versioned website', () => {
|
|||
expect(versionToSidebars).toMatchSnapshot(
|
||||
'sidebars needed for each version',
|
||||
);
|
||||
const routeConfigs = [];
|
||||
const dataContainer = {};
|
||||
const globalDataContainer = {};
|
||||
const actions = createFakeActions(
|
||||
routeConfigs,
|
||||
pluginContentDir,
|
||||
dataContainer,
|
||||
globalDataContainer,
|
||||
);
|
||||
const {actions, utils} = createFakeActions(pluginContentDir);
|
||||
await plugin.contentLoaded({
|
||||
content,
|
||||
actions,
|
||||
});
|
||||
|
||||
// The created base metadata for each nested docs route is smartly chunked/ splitted across version
|
||||
const latestVersionBaseMetadata = JSON.parse(
|
||||
dataContainer['docs-route-ff2.json'],
|
||||
const latestVersionBaseMetadata = utils.getCreatedDataByPrefix(
|
||||
'docs-route-',
|
||||
);
|
||||
expect(latestVersionBaseMetadata).toMatchSnapshot(
|
||||
'base metadata for latest version',
|
||||
|
@ -426,8 +442,8 @@ describe('versioned website', () => {
|
|||
expect(latestVersionBaseMetadata.permalinkToSidebar).not.toEqual(
|
||||
permalinkToSidebar,
|
||||
);
|
||||
const nextVersionBaseMetadata = JSON.parse(
|
||||
dataContainer['docs-next-route-1c8.json'],
|
||||
const nextVersionBaseMetadata = utils.getCreatedDataByPrefix(
|
||||
'docs-next-route-',
|
||||
);
|
||||
expect(nextVersionBaseMetadata).toMatchSnapshot(
|
||||
'base metadata for next version',
|
||||
|
@ -436,8 +452,8 @@ describe('versioned website', () => {
|
|||
expect(nextVersionBaseMetadata.permalinkToSidebar).not.toEqual(
|
||||
permalinkToSidebar,
|
||||
);
|
||||
const firstVersionBaseMetadata = JSON.parse(
|
||||
dataContainer['docs-1-0-0-route-660.json'],
|
||||
const firstVersionBaseMetadata = utils.getCreatedDataByPrefix(
|
||||
'docs-1-0-0-route-',
|
||||
);
|
||||
expect(firstVersionBaseMetadata).toMatchSnapshot(
|
||||
'base metadata for first version',
|
||||
|
@ -447,11 +463,151 @@ describe('versioned website', () => {
|
|||
permalinkToSidebar,
|
||||
);
|
||||
|
||||
// Sort the route config like in src/server/plugins/index.ts for consistent snapshot ordering
|
||||
sortConfig(routeConfigs);
|
||||
|
||||
expect(routeConfigs).not.toEqual([]);
|
||||
expect(routeConfigs).toMatchSnapshot();
|
||||
expect(globalDataContainer).toMatchSnapshot();
|
||||
utils.expectSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('versioned website (community)', () => {
|
||||
const siteDir = path.join(__dirname, '__fixtures__', 'versioned-site');
|
||||
const context = loadContext(siteDir);
|
||||
const sidebarPath = path.join(siteDir, 'community_sidebars.json');
|
||||
const routeBasePath = 'community';
|
||||
const pluginId = 'community';
|
||||
const plugin = pluginContentDocs(
|
||||
context,
|
||||
normalizePluginOptions(PluginOptionSchema, {
|
||||
id: 'community',
|
||||
path: 'community',
|
||||
routeBasePath,
|
||||
sidebarPath,
|
||||
}),
|
||||
);
|
||||
const env = loadEnv(siteDir, pluginId);
|
||||
const {docsDir: versionedDir} = env.versioning;
|
||||
const pluginContentDir = path.join(context.generatedFilesDir, plugin.name);
|
||||
|
||||
test('isVersioned', () => {
|
||||
expect(env.versioning.enabled).toEqual(true);
|
||||
});
|
||||
|
||||
test('extendCli - docsVersion', () => {
|
||||
const mock = jest.spyOn(version, 'docsVersion').mockImplementation();
|
||||
const cli = new commander.Command();
|
||||
plugin.extendCli(cli);
|
||||
cli.parse(['node', 'test', `docs:version:${pluginId}`, '2.0.0']);
|
||||
expect(mock).toHaveBeenCalledWith('2.0.0', siteDir, pluginId, {
|
||||
path: routeBasePath,
|
||||
sidebarPath,
|
||||
});
|
||||
mock.mockRestore();
|
||||
});
|
||||
|
||||
test('getPathToWatch', () => {
|
||||
const pathToWatch = plugin.getPathsToWatch();
|
||||
const matchPattern = pathToWatch.map((filepath) =>
|
||||
posixPath(path.relative(siteDir, filepath)),
|
||||
);
|
||||
expect(matchPattern).not.toEqual([]);
|
||||
expect(matchPattern).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"community/**/*.{md,mdx}",
|
||||
"community_versioned_sidebars/version-1.0.0-sidebars.json",
|
||||
"community_versioned_docs/version-1.0.0/**/*.{md,mdx}",
|
||||
"community_sidebars.json",
|
||||
]
|
||||
`);
|
||||
expect(isMatch('community/team.md', matchPattern)).toEqual(true);
|
||||
expect(
|
||||
isMatch('community_versioned_docs/version-1.0.0/team.md', matchPattern),
|
||||
).toEqual(true);
|
||||
|
||||
// Non existing version
|
||||
expect(
|
||||
isMatch('community_versioned_docs/version-2.0.0/team.md', matchPattern),
|
||||
).toEqual(false);
|
||||
expect(
|
||||
isMatch(
|
||||
'community_versioned_sidebars/version-2.0.0-sidebars.json',
|
||||
matchPattern,
|
||||
),
|
||||
).toEqual(false);
|
||||
|
||||
expect(isMatch('community/team.js', matchPattern)).toEqual(false);
|
||||
expect(
|
||||
isMatch('community_versioned_docs/version-1.0.0/team.js', matchPattern),
|
||||
).toEqual(false);
|
||||
});
|
||||
|
||||
test('content', async () => {
|
||||
const content = await plugin.loadContent();
|
||||
const {
|
||||
docsMetadata,
|
||||
docsSidebars,
|
||||
versionToSidebars,
|
||||
permalinkToSidebar,
|
||||
} = content;
|
||||
|
||||
expect(docsMetadata.team).toEqual({
|
||||
id: 'team',
|
||||
unversionedId: 'team',
|
||||
isDocsHomePage: false,
|
||||
permalink: '/community/next/team',
|
||||
source: path.join('@site', routeBasePath, 'team.md'),
|
||||
title: 'team',
|
||||
description: 'Team current version',
|
||||
version: 'next',
|
||||
sidebar: 'community',
|
||||
});
|
||||
expect(docsMetadata['version-1.0.0/team']).toEqual({
|
||||
id: 'version-1.0.0/team',
|
||||
unversionedId: 'team',
|
||||
isDocsHomePage: false,
|
||||
permalink: '/community/team',
|
||||
source: path.join(
|
||||
'@site',
|
||||
path.relative(siteDir, versionedDir),
|
||||
'version-1.0.0',
|
||||
'team.md',
|
||||
),
|
||||
title: 'team',
|
||||
description: 'Team 1.0.0',
|
||||
version: '1.0.0',
|
||||
sidebar: 'version-1.0.0/community',
|
||||
});
|
||||
|
||||
expect(docsSidebars).toMatchSnapshot('all sidebars');
|
||||
expect(versionToSidebars).toMatchSnapshot(
|
||||
'sidebars needed for each version',
|
||||
);
|
||||
|
||||
const {actions, utils} = createFakeActions(pluginContentDir);
|
||||
await plugin.contentLoaded({
|
||||
content,
|
||||
actions,
|
||||
});
|
||||
|
||||
// The created base metadata for each nested docs route is smartly chunked/ splitted across version
|
||||
const latestVersionBaseMetadata = utils.getCreatedDataByPrefix(
|
||||
'community-route-',
|
||||
);
|
||||
expect(latestVersionBaseMetadata).toMatchSnapshot(
|
||||
'base metadata for latest version',
|
||||
);
|
||||
expect(latestVersionBaseMetadata.docsSidebars).not.toEqual(docsSidebars);
|
||||
expect(latestVersionBaseMetadata.permalinkToSidebar).not.toEqual(
|
||||
permalinkToSidebar,
|
||||
);
|
||||
const nextVersionBaseMetadata = utils.getCreatedDataByPrefix(
|
||||
'community-next-route-',
|
||||
);
|
||||
expect(nextVersionBaseMetadata).toMatchSnapshot(
|
||||
'base metadata for next version',
|
||||
);
|
||||
expect(nextVersionBaseMetadata.docsSidebars).not.toEqual(docsSidebars);
|
||||
expect(nextVersionBaseMetadata.permalinkToSidebar).not.toEqual(
|
||||
permalinkToSidebar,
|
||||
);
|
||||
|
||||
utils.expectSnapshot();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -11,6 +11,7 @@ import processMetadata from '../metadata';
|
|||
import loadEnv from '../env';
|
||||
import {MetadataRaw, Env, MetadataOptions} from '../types';
|
||||
import {LoadContext} from '@docusaurus/types';
|
||||
import {DEFAULT_PLUGIN_ID} from '@docusaurus/core/lib/constants';
|
||||
|
||||
const fixtureDir = path.join(__dirname, '__fixtures__');
|
||||
|
||||
|
@ -66,7 +67,7 @@ describe('simple site', () => {
|
|||
const context = loadContext(siteDir);
|
||||
const routeBasePath = 'docs';
|
||||
const docsDir = path.resolve(siteDir, routeBasePath);
|
||||
const env = loadEnv(siteDir);
|
||||
const env = loadEnv(siteDir, DEFAULT_PLUGIN_ID);
|
||||
const options = {routeBasePath};
|
||||
|
||||
const {testMeta, testSlug} = createTestHelpers({
|
||||
|
@ -309,7 +310,7 @@ describe('versioned site', () => {
|
|||
const context = loadContext(siteDir);
|
||||
const routeBasePath = 'docs';
|
||||
const docsDir = path.resolve(siteDir, routeBasePath);
|
||||
const env = loadEnv(siteDir);
|
||||
const env = loadEnv(siteDir, DEFAULT_PLUGIN_ID);
|
||||
const {docsDir: versionedDir} = env.versioning;
|
||||
const options = {routeBasePath};
|
||||
|
||||
|
|
|
@ -6,17 +6,7 @@
|
|||
*/
|
||||
|
||||
import {PluginOptionSchema, DEFAULT_OPTIONS} from '../pluginOptionSchema';
|
||||
|
||||
export default function normalizePluginOptions(options) {
|
||||
const {value, error} = PluginOptionSchema.validate(options, {
|
||||
convert: false,
|
||||
});
|
||||
if (error) {
|
||||
throw error;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
import {normalizePluginOptions} from '@docusaurus/utils-validation';
|
||||
|
||||
// the type of remark/rehype plugins is function
|
||||
const remarkRehypePluginStub = () => {};
|
||||
|
@ -63,7 +53,7 @@ describe('normalizeDocsPluginOptions', () => {
|
|||
|
||||
test('should reject bad path inputs', () => {
|
||||
expect(() => {
|
||||
normalizePluginOptions({
|
||||
normalizePluginOptions(PluginOptionSchema, {
|
||||
path: 2,
|
||||
});
|
||||
}).toThrowErrorMatchingInlineSnapshot(`"\\"path\\" must be a string"`);
|
||||
|
@ -71,7 +61,7 @@ describe('normalizeDocsPluginOptions', () => {
|
|||
|
||||
test('should reject bad include inputs', () => {
|
||||
expect(() => {
|
||||
normalizePluginOptions({
|
||||
normalizePluginOptions(PluginOptionSchema, {
|
||||
include: '**/*.{md,mdx}',
|
||||
});
|
||||
}).toThrowErrorMatchingInlineSnapshot(`"\\"include\\" must be an array"`);
|
||||
|
@ -79,7 +69,7 @@ describe('normalizeDocsPluginOptions', () => {
|
|||
|
||||
test('should reject bad showLastUpdateTime inputs', () => {
|
||||
expect(() => {
|
||||
normalizePluginOptions({
|
||||
normalizePluginOptions(PluginOptionSchema, {
|
||||
showLastUpdateTime: 'true',
|
||||
});
|
||||
}).toThrowErrorMatchingInlineSnapshot(
|
||||
|
@ -89,7 +79,7 @@ describe('normalizeDocsPluginOptions', () => {
|
|||
|
||||
test('should reject bad remarkPlugins input', () => {
|
||||
expect(() => {
|
||||
normalizePluginOptions({
|
||||
normalizePluginOptions(PluginOptionSchema, {
|
||||
remarkPlugins: 'remark-math',
|
||||
});
|
||||
}).toThrowErrorMatchingInlineSnapshot(
|
||||
|
|
|
@ -14,6 +14,7 @@ import {
|
|||
getVersionsJSONFile,
|
||||
getVersionedSidebarsDir,
|
||||
} from '../env';
|
||||
import {DEFAULT_PLUGIN_ID} from '@docusaurus/core/lib/constants';
|
||||
|
||||
const fixtureDir = path.join(__dirname, '__fixtures__');
|
||||
|
||||
|
@ -27,87 +28,114 @@ describe('docsVersion', () => {
|
|||
|
||||
test('no version tag provided', () => {
|
||||
expect(() =>
|
||||
docsVersion(null, simpleSiteDir, DEFAULT_OPTIONS),
|
||||
docsVersion(null, simpleSiteDir, DEFAULT_PLUGIN_ID, DEFAULT_OPTIONS),
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"No version tag specified!. Pass the version you wish to create as an argument. Ex: 1.0.0"`,
|
||||
`"[docs] No version tag specified!. Pass the version you wish to create as an argument. Ex: 1.0.0"`,
|
||||
);
|
||||
expect(() =>
|
||||
docsVersion(undefined, simpleSiteDir, DEFAULT_OPTIONS),
|
||||
docsVersion(undefined, simpleSiteDir, DEFAULT_PLUGIN_ID, DEFAULT_OPTIONS),
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"No version tag specified!. Pass the version you wish to create as an argument. Ex: 1.0.0"`,
|
||||
`"[docs] No version tag specified!. Pass the version you wish to create as an argument. Ex: 1.0.0"`,
|
||||
);
|
||||
expect(() =>
|
||||
docsVersion('', simpleSiteDir, DEFAULT_OPTIONS),
|
||||
docsVersion('', simpleSiteDir, DEFAULT_PLUGIN_ID, DEFAULT_OPTIONS),
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"No version tag specified!. Pass the version you wish to create as an argument. Ex: 1.0.0"`,
|
||||
`"[docs] No version tag specified!. Pass the version you wish to create as an argument. Ex: 1.0.0"`,
|
||||
);
|
||||
});
|
||||
|
||||
test('version tag should not have slash', () => {
|
||||
expect(() =>
|
||||
docsVersion('foo/bar', simpleSiteDir, DEFAULT_OPTIONS),
|
||||
docsVersion('foo/bar', simpleSiteDir, DEFAULT_PLUGIN_ID, DEFAULT_OPTIONS),
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Invalid version tag specified! Do not include slash (/) or (\\\\). Try something like: 1.0.0"`,
|
||||
`"[docs] Invalid version tag specified! Do not include slash (/) or (\\\\). Try something like: 1.0.0"`,
|
||||
);
|
||||
expect(() =>
|
||||
docsVersion('foo\\bar', simpleSiteDir, DEFAULT_OPTIONS),
|
||||
docsVersion(
|
||||
'foo\\bar',
|
||||
simpleSiteDir,
|
||||
DEFAULT_PLUGIN_ID,
|
||||
DEFAULT_OPTIONS,
|
||||
),
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Invalid version tag specified! Do not include slash (/) or (\\\\). Try something like: 1.0.0"`,
|
||||
`"[docs] Invalid version tag specified! Do not include slash (/) or (\\\\). Try something like: 1.0.0"`,
|
||||
);
|
||||
});
|
||||
|
||||
test('version tag should not be too long', () => {
|
||||
expect(() =>
|
||||
docsVersion('a'.repeat(255), simpleSiteDir, DEFAULT_OPTIONS),
|
||||
docsVersion(
|
||||
'a'.repeat(255),
|
||||
simpleSiteDir,
|
||||
DEFAULT_PLUGIN_ID,
|
||||
DEFAULT_OPTIONS,
|
||||
),
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Invalid version tag specified! Length must <= 32 characters. Try something like: 1.0.0"`,
|
||||
`"[docs] Invalid version tag specified! Length must <= 32 characters. Try something like: 1.0.0"`,
|
||||
);
|
||||
});
|
||||
|
||||
test('version tag should not be a dot or two dots', () => {
|
||||
expect(() =>
|
||||
docsVersion('..', simpleSiteDir, DEFAULT_OPTIONS),
|
||||
docsVersion('..', simpleSiteDir, DEFAULT_PLUGIN_ID, DEFAULT_OPTIONS),
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Invalid version tag specified! Do not name your version \\".\\" or \\"..\\". Try something like: 1.0.0"`,
|
||||
`"[docs] Invalid version tag specified! Do not name your version \\".\\" or \\"..\\". Try something like: 1.0.0"`,
|
||||
);
|
||||
expect(() =>
|
||||
docsVersion('.', simpleSiteDir, DEFAULT_OPTIONS),
|
||||
docsVersion('.', simpleSiteDir, DEFAULT_PLUGIN_ID, DEFAULT_OPTIONS),
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Invalid version tag specified! Do not name your version \\".\\" or \\"..\\". Try something like: 1.0.0"`,
|
||||
`"[docs] Invalid version tag specified! Do not name your version \\".\\" or \\"..\\". Try something like: 1.0.0"`,
|
||||
);
|
||||
});
|
||||
|
||||
test('version tag should be a valid pathname', () => {
|
||||
expect(() =>
|
||||
docsVersion('<foo|bar>', simpleSiteDir, DEFAULT_OPTIONS),
|
||||
docsVersion(
|
||||
'<foo|bar>',
|
||||
simpleSiteDir,
|
||||
DEFAULT_PLUGIN_ID,
|
||||
DEFAULT_OPTIONS,
|
||||
),
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Invalid version tag specified! Please ensure its a valid pathname too. Try something like: 1.0.0"`,
|
||||
`"[docs] Invalid version tag specified! Please ensure its a valid pathname too. Try something like: 1.0.0"`,
|
||||
);
|
||||
expect(() =>
|
||||
docsVersion('foo\x00bar', simpleSiteDir, DEFAULT_OPTIONS),
|
||||
docsVersion(
|
||||
'foo\x00bar',
|
||||
simpleSiteDir,
|
||||
DEFAULT_PLUGIN_ID,
|
||||
DEFAULT_OPTIONS,
|
||||
),
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Invalid version tag specified! Please ensure its a valid pathname too. Try something like: 1.0.0"`,
|
||||
`"[docs] Invalid version tag specified! Please ensure its a valid pathname too. Try something like: 1.0.0"`,
|
||||
);
|
||||
expect(() =>
|
||||
docsVersion('foo:bar', simpleSiteDir, DEFAULT_OPTIONS),
|
||||
docsVersion('foo:bar', simpleSiteDir, DEFAULT_PLUGIN_ID, DEFAULT_OPTIONS),
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Invalid version tag specified! Please ensure its a valid pathname too. Try something like: 1.0.0"`,
|
||||
`"[docs] Invalid version tag specified! Please ensure its a valid pathname too. Try something like: 1.0.0"`,
|
||||
);
|
||||
});
|
||||
|
||||
test('version tag already exist', () => {
|
||||
expect(() =>
|
||||
docsVersion('1.0.0', versionedSiteDir, DEFAULT_OPTIONS),
|
||||
docsVersion(
|
||||
'1.0.0',
|
||||
versionedSiteDir,
|
||||
DEFAULT_PLUGIN_ID,
|
||||
DEFAULT_OPTIONS,
|
||||
),
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"This version already exists!. Use a version tag that does not already exist."`,
|
||||
`"[docs] This version already exists!. Use a version tag that does not already exist."`,
|
||||
);
|
||||
});
|
||||
|
||||
test('no docs file to version', () => {
|
||||
const emptySiteDir = path.join(fixtureDir, 'empty-site');
|
||||
expect(() =>
|
||||
docsVersion('1.0.0', emptySiteDir, DEFAULT_OPTIONS),
|
||||
).toThrowErrorMatchingInlineSnapshot(`"There is no docs to version !"`);
|
||||
docsVersion('1.0.0', emptySiteDir, DEFAULT_PLUGIN_ID, DEFAULT_OPTIONS),
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"[docs] There is no docs to version !"`,
|
||||
);
|
||||
});
|
||||
|
||||
test('first time versioning', () => {
|
||||
|
@ -131,21 +159,26 @@ describe('docsVersion', () => {
|
|||
path: 'docs',
|
||||
sidebarPath: path.join(simpleSiteDir, 'sidebars.json'),
|
||||
};
|
||||
docsVersion('1.0.0', simpleSiteDir, options);
|
||||
docsVersion('1.0.0', simpleSiteDir, DEFAULT_PLUGIN_ID, options);
|
||||
expect(copyMock).toHaveBeenCalledWith(
|
||||
path.join(simpleSiteDir, options.path),
|
||||
path.join(getVersionedDocsDir(simpleSiteDir), 'version-1.0.0'),
|
||||
path.join(
|
||||
getVersionedDocsDir(simpleSiteDir, DEFAULT_PLUGIN_ID),
|
||||
'version-1.0.0',
|
||||
),
|
||||
);
|
||||
expect(versionedSidebar).toMatchSnapshot();
|
||||
expect(versionedSidebarPath).toEqual(
|
||||
path.join(
|
||||
getVersionedSidebarsDir(simpleSiteDir),
|
||||
getVersionedSidebarsDir(simpleSiteDir, DEFAULT_PLUGIN_ID),
|
||||
'version-1.0.0-sidebars.json',
|
||||
),
|
||||
);
|
||||
expect(versionsPath).toEqual(getVersionsJSONFile(simpleSiteDir));
|
||||
expect(versionsPath).toEqual(
|
||||
getVersionsJSONFile(simpleSiteDir, DEFAULT_PLUGIN_ID),
|
||||
);
|
||||
expect(versions).toEqual(['1.0.0']);
|
||||
expect(consoleMock).toHaveBeenCalledWith('Version 1.0.0 created!');
|
||||
expect(consoleMock).toHaveBeenCalledWith('[docs] Version 1.0.0 created!');
|
||||
|
||||
copyMock.mockRestore();
|
||||
writeMock.mockRestore();
|
||||
|
@ -174,21 +207,78 @@ describe('docsVersion', () => {
|
|||
path: 'docs',
|
||||
sidebarPath: path.join(versionedSiteDir, 'sidebars.json'),
|
||||
};
|
||||
docsVersion('2.0.0', versionedSiteDir, options);
|
||||
docsVersion('2.0.0', versionedSiteDir, DEFAULT_PLUGIN_ID, options);
|
||||
expect(copyMock).toHaveBeenCalledWith(
|
||||
path.join(versionedSiteDir, options.path),
|
||||
path.join(getVersionedDocsDir(versionedSiteDir), 'version-2.0.0'),
|
||||
path.join(
|
||||
getVersionedDocsDir(versionedSiteDir, DEFAULT_PLUGIN_ID),
|
||||
'version-2.0.0',
|
||||
),
|
||||
);
|
||||
expect(versionedSidebar).toMatchSnapshot();
|
||||
expect(versionedSidebarPath).toEqual(
|
||||
path.join(
|
||||
getVersionedSidebarsDir(versionedSiteDir),
|
||||
getVersionedSidebarsDir(versionedSiteDir, DEFAULT_PLUGIN_ID),
|
||||
'version-2.0.0-sidebars.json',
|
||||
),
|
||||
);
|
||||
expect(versionsPath).toEqual(getVersionsJSONFile(versionedSiteDir));
|
||||
expect(versionsPath).toEqual(
|
||||
getVersionsJSONFile(versionedSiteDir, DEFAULT_PLUGIN_ID),
|
||||
);
|
||||
expect(versions).toEqual(['2.0.0', '1.0.1', '1.0.0', 'withSlugs']);
|
||||
expect(consoleMock).toHaveBeenCalledWith('Version 2.0.0 created!');
|
||||
expect(consoleMock).toHaveBeenCalledWith('[docs] Version 2.0.0 created!');
|
||||
|
||||
copyMock.mockRestore();
|
||||
writeMock.mockRestore();
|
||||
consoleMock.mockRestore();
|
||||
ensureMock.mockRestore();
|
||||
});
|
||||
|
||||
test('second docs instance versioning', () => {
|
||||
const pluginId = 'community';
|
||||
|
||||
const copyMock = jest.spyOn(fs, 'copySync').mockImplementation();
|
||||
const ensureMock = jest.spyOn(fs, 'ensureDirSync').mockImplementation();
|
||||
const writeMock = jest.spyOn(fs, 'writeFileSync');
|
||||
let versionedSidebar;
|
||||
let versionedSidebarPath;
|
||||
writeMock.mockImplementationOnce((filepath, content) => {
|
||||
versionedSidebarPath = filepath;
|
||||
versionedSidebar = JSON.parse(content);
|
||||
});
|
||||
let versionsPath;
|
||||
let versions;
|
||||
writeMock.mockImplementationOnce((filepath, content) => {
|
||||
versionsPath = filepath;
|
||||
versions = JSON.parse(content);
|
||||
});
|
||||
const consoleMock = jest.spyOn(console, 'log').mockImplementation();
|
||||
const options = {
|
||||
path: 'community',
|
||||
sidebarPath: path.join(versionedSiteDir, 'community_sidebars.json'),
|
||||
};
|
||||
docsVersion('2.0.0', versionedSiteDir, pluginId, options);
|
||||
expect(copyMock).toHaveBeenCalledWith(
|
||||
path.join(versionedSiteDir, options.path),
|
||||
path.join(
|
||||
getVersionedDocsDir(versionedSiteDir, pluginId),
|
||||
'version-2.0.0',
|
||||
),
|
||||
);
|
||||
expect(versionedSidebar).toMatchSnapshot();
|
||||
expect(versionedSidebarPath).toEqual(
|
||||
path.join(
|
||||
getVersionedSidebarsDir(versionedSiteDir, pluginId),
|
||||
'version-2.0.0-sidebars.json',
|
||||
),
|
||||
);
|
||||
expect(versionsPath).toEqual(
|
||||
getVersionsJSONFile(versionedSiteDir, pluginId),
|
||||
);
|
||||
expect(versions).toEqual(['2.0.0', '1.0.0']);
|
||||
expect(consoleMock).toHaveBeenCalledWith(
|
||||
'[community] Version 2.0.0 created!',
|
||||
);
|
||||
|
||||
copyMock.mockRestore();
|
||||
writeMock.mockRestore();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue