mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-10 15:47:23 +02:00
1298 lines
34 KiB
TypeScript
1298 lines
34 KiB
TypeScript
/**
|
|
* 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.
|
|
*/
|
|
|
|
import {jest} from '@jest/globals';
|
|
import path from 'path';
|
|
import {loadContext} from '@docusaurus/core/src/server/index';
|
|
import {createSlugger, posixPath, DEFAULT_PLUGIN_ID} from '@docusaurus/utils';
|
|
import {createSidebarsUtils} from '../sidebars/utils';
|
|
import {
|
|
processDocMetadata,
|
|
readVersionDocs,
|
|
readDocFile,
|
|
addDocNavigation,
|
|
isCategoryIndex,
|
|
type DocEnv,
|
|
} from '../docs';
|
|
import {loadSidebars} from '../sidebars';
|
|
import {readVersionsMetadata} from '../versions';
|
|
import {DEFAULT_OPTIONS} from '../options';
|
|
import type {Sidebars} from '../sidebars/types';
|
|
import type {DocFile} from '../types';
|
|
import type {
|
|
MetadataOptions,
|
|
PluginOptions,
|
|
EditUrlFunction,
|
|
DocMetadataBase,
|
|
VersionMetadata,
|
|
PropNavigationLink,
|
|
} from '@docusaurus/plugin-content-docs';
|
|
import type {LoadContext} from '@docusaurus/types';
|
|
import type {Optional} from 'utility-types';
|
|
|
|
const fixtureDir = path.join(__dirname, '__fixtures__');
|
|
|
|
const createFakeDocFile = ({
|
|
source,
|
|
frontMatter = {},
|
|
markdown = 'some markdown content',
|
|
}: {
|
|
source: string;
|
|
frontMatter?: {[key: string]: string};
|
|
markdown?: string;
|
|
}): DocFile => {
|
|
const content = `---
|
|
${Object.entries(frontMatter)
|
|
.map(([key, value]) => `${key}: ${value}`)
|
|
.join('\n')}
|
|
---
|
|
${markdown}
|
|
`;
|
|
return {
|
|
source,
|
|
content,
|
|
contentPath: 'docs',
|
|
filePath: source,
|
|
};
|
|
};
|
|
|
|
type TestUtilsArg = {
|
|
siteDir: string;
|
|
context: LoadContext;
|
|
versionMetadata: VersionMetadata;
|
|
options: MetadataOptions;
|
|
env?: DocEnv;
|
|
};
|
|
|
|
function createTestUtils({
|
|
siteDir,
|
|
context,
|
|
versionMetadata,
|
|
options,
|
|
env = 'production',
|
|
}: TestUtilsArg) {
|
|
async function readDoc(docFileSource: string) {
|
|
return readDocFile(versionMetadata, docFileSource);
|
|
}
|
|
async function processDocFile(docFileArg: DocFile | string) {
|
|
const docFile: DocFile =
|
|
typeof docFileArg === 'string' ? await readDoc(docFileArg) : docFileArg;
|
|
|
|
return processDocMetadata({
|
|
docFile,
|
|
versionMetadata,
|
|
options,
|
|
context,
|
|
env,
|
|
});
|
|
}
|
|
|
|
// Makes it easier to assert failure cases
|
|
async function getProcessDocFileError(
|
|
docFileArg: DocFile | string,
|
|
): Promise<Error> {
|
|
try {
|
|
await processDocFile(docFileArg);
|
|
return new Error("unexpected: getProcessDocFileError didn't crash");
|
|
} catch (e) {
|
|
return e as Error;
|
|
}
|
|
}
|
|
|
|
async function testMeta(
|
|
docFileSource: string,
|
|
expectedMetadata: Optional<
|
|
DocMetadataBase,
|
|
'source' | 'lastUpdatedBy' | 'lastUpdatedAt' | 'editUrl' | 'draft'
|
|
>,
|
|
) {
|
|
const docFile = await readDoc(docFileSource);
|
|
const metadata = await processDocFile(docFile);
|
|
expect(metadata).toEqual({
|
|
lastUpdatedBy: undefined,
|
|
lastUpdatedAt: undefined,
|
|
editUrl: undefined,
|
|
draft: false,
|
|
source: path.posix.join(
|
|
'@site',
|
|
posixPath(path.relative(siteDir, versionMetadata.contentPath)),
|
|
posixPath(docFileSource),
|
|
),
|
|
...expectedMetadata,
|
|
});
|
|
}
|
|
|
|
async function testSlug(docFileSource: string, expectedPermalink: string) {
|
|
const docFile = await readDoc(docFileSource);
|
|
const metadata = await processDocMetadata({
|
|
docFile,
|
|
versionMetadata,
|
|
context,
|
|
options,
|
|
env,
|
|
});
|
|
expect(metadata.permalink).toEqual(expectedPermalink);
|
|
}
|
|
|
|
async function generateNavigation(docFiles: DocFile[]): Promise<{
|
|
pagination: {
|
|
prev?: PropNavigationLink;
|
|
next?: PropNavigationLink;
|
|
id: string;
|
|
}[];
|
|
sidebars: Sidebars;
|
|
}> {
|
|
const rawDocs = await Promise.all(
|
|
docFiles.map(async (docFile) =>
|
|
processDocMetadata({
|
|
docFile,
|
|
versionMetadata,
|
|
context,
|
|
options,
|
|
env: 'production',
|
|
}),
|
|
),
|
|
);
|
|
const sidebars = await loadSidebars(versionMetadata.sidebarFilePath, {
|
|
sidebarItemsGenerator: ({defaultSidebarItemsGenerator, ...args}) =>
|
|
defaultSidebarItemsGenerator({...args}),
|
|
numberPrefixParser: options.numberPrefixParser,
|
|
docs: rawDocs,
|
|
drafts: [],
|
|
version: versionMetadata,
|
|
sidebarOptions: {
|
|
sidebarCollapsed: false,
|
|
sidebarCollapsible: true,
|
|
},
|
|
categoryLabelSlugger: createSlugger(),
|
|
});
|
|
const sidebarsUtils = createSidebarsUtils(sidebars);
|
|
|
|
return {
|
|
pagination: addDocNavigation(
|
|
rawDocs,
|
|
sidebarsUtils,
|
|
versionMetadata.sidebarFilePath as string,
|
|
).map((doc) => ({prev: doc.previous, next: doc.next, id: doc.id})),
|
|
sidebars,
|
|
};
|
|
}
|
|
|
|
return {
|
|
processDocFile,
|
|
getProcessDocFileError,
|
|
testMeta,
|
|
testSlug,
|
|
generateNavigation,
|
|
};
|
|
}
|
|
|
|
describe('simple site', () => {
|
|
async function loadSite(
|
|
loadSiteOptions: {options: Partial<PluginOptions>} = {options: {}},
|
|
) {
|
|
const siteDir = path.join(fixtureDir, 'simple-site');
|
|
const context = await loadContext({siteDir});
|
|
const options = {
|
|
id: DEFAULT_PLUGIN_ID,
|
|
...DEFAULT_OPTIONS,
|
|
...loadSiteOptions.options,
|
|
};
|
|
const versionsMetadata = await readVersionsMetadata({
|
|
context,
|
|
options,
|
|
});
|
|
expect(versionsMetadata).toHaveLength(1);
|
|
const currentVersion = versionsMetadata[0]!;
|
|
|
|
function createTestUtilsPartial(args: Partial<TestUtilsArg>) {
|
|
return createTestUtils({
|
|
siteDir,
|
|
context,
|
|
options,
|
|
versionMetadata: currentVersion,
|
|
...args,
|
|
});
|
|
}
|
|
|
|
const defaultTestUtils = createTestUtilsPartial({});
|
|
|
|
return {
|
|
siteDir,
|
|
context,
|
|
options,
|
|
versionsMetadata,
|
|
defaultTestUtils,
|
|
createTestUtilsPartial,
|
|
currentVersion,
|
|
};
|
|
}
|
|
|
|
it('readVersionDocs', async () => {
|
|
const {options, currentVersion} = await loadSite();
|
|
const docs = await readVersionDocs(currentVersion, options);
|
|
expect(docs.map((doc) => doc.source).sort()).toEqual(
|
|
[
|
|
'hello.md',
|
|
'ipsum.md',
|
|
'lorem.md',
|
|
'rootAbsoluteSlug.md',
|
|
'rootRelativeSlug.md',
|
|
'rootResolvedSlug.md',
|
|
'rootTryToEscapeSlug.md',
|
|
'headingAsTitle.md',
|
|
'doc with space.md',
|
|
'doc-draft.md',
|
|
'customLastUpdate.md',
|
|
'lastUpdateAuthorOnly.md',
|
|
'lastUpdateDateOnly.md',
|
|
'foo/bar.md',
|
|
'foo/baz.md',
|
|
'slugs/absoluteSlug.md',
|
|
'slugs/relativeSlug.md',
|
|
'slugs/resolvedSlug.md',
|
|
'slugs/tryToEscapeSlug.md',
|
|
].sort(),
|
|
);
|
|
});
|
|
|
|
it('normal docs', async () => {
|
|
const {defaultTestUtils} = await loadSite();
|
|
await defaultTestUtils.testMeta(path.join('foo', 'bar.md'), {
|
|
version: 'current',
|
|
id: 'foo/bar',
|
|
unversionedId: 'foo/bar',
|
|
sourceDirName: 'foo',
|
|
permalink: '/docs/foo/bar',
|
|
slug: '/foo/bar',
|
|
title: 'Bar',
|
|
description: 'This is custom description',
|
|
frontMatter: {
|
|
description: 'This is custom description',
|
|
id: 'bar',
|
|
title: 'Bar',
|
|
pagination_next: null,
|
|
pagination_prev: null,
|
|
},
|
|
tags: [],
|
|
});
|
|
await defaultTestUtils.testMeta(path.join('hello.md'), {
|
|
version: 'current',
|
|
id: 'hello',
|
|
unversionedId: 'hello',
|
|
sourceDirName: '.',
|
|
permalink: '/docs/',
|
|
slug: '/',
|
|
title: 'Hello, World !',
|
|
description: `Hi, Endilie here :)`,
|
|
frontMatter: {
|
|
id: 'hello',
|
|
title: 'Hello, World !',
|
|
sidebar_label: 'Hello sidebar_label',
|
|
slug: '/',
|
|
tags: ['tag-1', 'tag 3'],
|
|
},
|
|
tags: [
|
|
{
|
|
label: 'tag-1',
|
|
permalink: '/docs/tags/tag-1',
|
|
},
|
|
{
|
|
label: 'tag 3',
|
|
permalink: '/docs/tags/tag-3',
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
it('docs with editUrl', async () => {
|
|
const {siteDir, context, options, currentVersion, createTestUtilsPartial} =
|
|
await loadSite({
|
|
options: {
|
|
editUrl: 'https://github.com/facebook/docusaurus/edit/main/website',
|
|
},
|
|
});
|
|
|
|
const testUtilsLocal = createTestUtilsPartial({
|
|
siteDir,
|
|
context,
|
|
options,
|
|
versionMetadata: currentVersion,
|
|
});
|
|
|
|
await testUtilsLocal.testMeta(path.join('foo', 'baz.md'), {
|
|
version: 'current',
|
|
id: 'foo/baz',
|
|
unversionedId: 'foo/baz',
|
|
sourceDirName: 'foo',
|
|
permalink: '/docs/foo/bazSlug.html',
|
|
slug: '/foo/bazSlug.html',
|
|
title: 'baz',
|
|
editUrl:
|
|
'https://github.com/facebook/docusaurus/edit/main/website/docs/foo/baz.md',
|
|
description: 'Images',
|
|
frontMatter: {
|
|
id: 'baz',
|
|
slug: 'bazSlug.html',
|
|
title: 'baz',
|
|
pagination_label: 'baz pagination_label',
|
|
tags: [
|
|
'tag 1',
|
|
'tag-1',
|
|
{label: 'tag 2', permalink: 'tag2-custom-permalink'},
|
|
],
|
|
},
|
|
tags: [
|
|
{
|
|
label: 'tag 1',
|
|
permalink: '/docs/tags/tag-1',
|
|
},
|
|
{
|
|
label: 'tag 2',
|
|
permalink: '/docs/tags/tag2-custom-permalink',
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
it('docs with custom editUrl & unrelated frontMatter', async () => {
|
|
const {defaultTestUtils} = await loadSite();
|
|
|
|
await defaultTestUtils.testMeta('lorem.md', {
|
|
version: 'current',
|
|
id: 'lorem',
|
|
unversionedId: 'lorem',
|
|
sourceDirName: '.',
|
|
permalink: '/docs/lorem',
|
|
slug: '/lorem',
|
|
title: 'lorem',
|
|
editUrl: 'https://github.com/customUrl/docs/lorem.md',
|
|
description: 'Lorem ipsum.',
|
|
frontMatter: {
|
|
custom_edit_url: 'https://github.com/customUrl/docs/lorem.md',
|
|
unrelated_front_matter: "won't be part of metadata",
|
|
},
|
|
tags: [],
|
|
});
|
|
});
|
|
|
|
it('docs with function editUrl', async () => {
|
|
const hardcodedEditUrl = 'hardcoded-edit-url';
|
|
|
|
const editUrlFunction: EditUrlFunction = jest.fn(() => hardcodedEditUrl);
|
|
|
|
const {siteDir, context, options, currentVersion, createTestUtilsPartial} =
|
|
await loadSite({
|
|
options: {
|
|
editUrl: editUrlFunction,
|
|
},
|
|
});
|
|
|
|
const testUtilsLocal = createTestUtilsPartial({
|
|
siteDir,
|
|
context,
|
|
options,
|
|
versionMetadata: currentVersion,
|
|
});
|
|
|
|
await testUtilsLocal.testMeta(path.join('foo', 'baz.md'), {
|
|
version: 'current',
|
|
id: 'foo/baz',
|
|
unversionedId: 'foo/baz',
|
|
sourceDirName: 'foo',
|
|
permalink: '/docs/foo/bazSlug.html',
|
|
slug: '/foo/bazSlug.html',
|
|
title: 'baz',
|
|
editUrl: hardcodedEditUrl,
|
|
description: 'Images',
|
|
frontMatter: {
|
|
id: 'baz',
|
|
slug: 'bazSlug.html',
|
|
title: 'baz',
|
|
pagination_label: 'baz pagination_label',
|
|
tags: [
|
|
'tag 1',
|
|
'tag-1',
|
|
{label: 'tag 2', permalink: 'tag2-custom-permalink'},
|
|
],
|
|
},
|
|
tags: [
|
|
{
|
|
label: 'tag 1',
|
|
permalink: '/docs/tags/tag-1',
|
|
},
|
|
{
|
|
label: 'tag 2',
|
|
permalink: '/docs/tags/tag2-custom-permalink',
|
|
},
|
|
],
|
|
});
|
|
|
|
expect(editUrlFunction).toHaveBeenCalledTimes(1);
|
|
expect(editUrlFunction).toHaveBeenCalledWith({
|
|
version: 'current',
|
|
versionDocsDirPath: 'docs',
|
|
docPath: path.posix.join('foo', 'baz.md'),
|
|
permalink: '/docs/foo/bazSlug.html',
|
|
locale: 'en',
|
|
});
|
|
});
|
|
|
|
it('docs with last update time and author', async () => {
|
|
const {siteDir, context, options, currentVersion, createTestUtilsPartial} =
|
|
await loadSite({
|
|
options: {
|
|
showLastUpdateAuthor: true,
|
|
showLastUpdateTime: true,
|
|
},
|
|
});
|
|
|
|
const testUtilsLocal = createTestUtilsPartial({
|
|
siteDir,
|
|
context,
|
|
options,
|
|
versionMetadata: currentVersion,
|
|
});
|
|
|
|
await testUtilsLocal.testMeta('lorem.md', {
|
|
version: 'current',
|
|
id: 'lorem',
|
|
unversionedId: 'lorem',
|
|
sourceDirName: '.',
|
|
permalink: '/docs/lorem',
|
|
slug: '/lorem',
|
|
title: 'lorem',
|
|
editUrl: 'https://github.com/customUrl/docs/lorem.md',
|
|
description: 'Lorem ipsum.',
|
|
frontMatter: {
|
|
custom_edit_url: 'https://github.com/customUrl/docs/lorem.md',
|
|
unrelated_front_matter: "won't be part of metadata",
|
|
},
|
|
lastUpdatedAt: 1539502055,
|
|
formattedLastUpdatedAt: 'Oct 14, 2018',
|
|
lastUpdatedBy: 'Author',
|
|
tags: [],
|
|
});
|
|
});
|
|
|
|
it('docs with draft frontmatter', async () => {
|
|
const {createTestUtilsPartial} = await loadSite();
|
|
|
|
const testUtilsProd = createTestUtilsPartial({
|
|
env: 'production',
|
|
});
|
|
await expect(
|
|
testUtilsProd.processDocFile('doc-draft.md'),
|
|
).resolves.toMatchObject({
|
|
draft: true,
|
|
});
|
|
|
|
const testUtilsDev = createTestUtilsPartial({
|
|
env: 'development',
|
|
});
|
|
await expect(
|
|
testUtilsDev.processDocFile('doc-draft.md'),
|
|
).resolves.toMatchObject({
|
|
draft: false,
|
|
});
|
|
});
|
|
|
|
it('docs with last_update front matter', async () => {
|
|
const {siteDir, context, options, currentVersion, createTestUtilsPartial} =
|
|
await loadSite({
|
|
options: {
|
|
showLastUpdateAuthor: true,
|
|
showLastUpdateTime: true,
|
|
},
|
|
});
|
|
|
|
const testUtilsLocal = createTestUtilsPartial({
|
|
siteDir,
|
|
context,
|
|
options,
|
|
versionMetadata: currentVersion,
|
|
});
|
|
|
|
await testUtilsLocal.testMeta('customLastUpdate.md', {
|
|
version: 'current',
|
|
id: 'customLastUpdate',
|
|
unversionedId: 'customLastUpdate',
|
|
sourceDirName: '.',
|
|
permalink: '/docs/customLastUpdate',
|
|
slug: '/customLastUpdate',
|
|
title: 'Custom Last Update',
|
|
description: 'Custom last update',
|
|
frontMatter: {
|
|
last_update: {
|
|
author: 'Custom Author',
|
|
date: '1/1/2000',
|
|
},
|
|
title: 'Custom Last Update',
|
|
},
|
|
lastUpdatedAt: new Date('1/1/2000').getTime() / 1000,
|
|
formattedLastUpdatedAt: 'Jan 1, 2000',
|
|
lastUpdatedBy: 'Custom Author',
|
|
sidebarPosition: undefined,
|
|
tags: [],
|
|
});
|
|
});
|
|
|
|
it('docs with only last_update author front matter', async () => {
|
|
const {siteDir, context, options, currentVersion, createTestUtilsPartial} =
|
|
await loadSite({
|
|
options: {
|
|
showLastUpdateAuthor: true,
|
|
showLastUpdateTime: true,
|
|
},
|
|
});
|
|
|
|
const testUtilsLocal = createTestUtilsPartial({
|
|
siteDir,
|
|
context,
|
|
options,
|
|
versionMetadata: currentVersion,
|
|
});
|
|
|
|
await testUtilsLocal.testMeta('lastUpdateAuthorOnly.md', {
|
|
version: 'current',
|
|
id: 'lastUpdateAuthorOnly',
|
|
unversionedId: 'lastUpdateAuthorOnly',
|
|
sourceDirName: '.',
|
|
permalink: '/docs/lastUpdateAuthorOnly',
|
|
slug: '/lastUpdateAuthorOnly',
|
|
title: 'Last Update Author Only',
|
|
description: 'Only custom author, so it will still use the date from Git',
|
|
frontMatter: {
|
|
last_update: {
|
|
author: 'Custom Author',
|
|
},
|
|
title: 'Last Update Author Only',
|
|
},
|
|
lastUpdatedAt: 1539502055,
|
|
formattedLastUpdatedAt: 'Oct 14, 2018',
|
|
lastUpdatedBy: 'Custom Author',
|
|
sidebarPosition: undefined,
|
|
tags: [],
|
|
});
|
|
});
|
|
|
|
it('docs with only last_update date front matter', async () => {
|
|
const {siteDir, context, options, currentVersion, createTestUtilsPartial} =
|
|
await loadSite({
|
|
options: {
|
|
showLastUpdateAuthor: true,
|
|
showLastUpdateTime: true,
|
|
},
|
|
});
|
|
|
|
const testUtilsLocal = createTestUtilsPartial({
|
|
siteDir,
|
|
context,
|
|
options,
|
|
versionMetadata: currentVersion,
|
|
});
|
|
|
|
await testUtilsLocal.testMeta('lastUpdateDateOnly.md', {
|
|
version: 'current',
|
|
id: 'lastUpdateDateOnly',
|
|
unversionedId: 'lastUpdateDateOnly',
|
|
sourceDirName: '.',
|
|
permalink: '/docs/lastUpdateDateOnly',
|
|
slug: '/lastUpdateDateOnly',
|
|
title: 'Last Update Date Only',
|
|
description: 'Only custom date, so it will still use the author from Git',
|
|
frontMatter: {
|
|
last_update: {
|
|
date: '1/1/2000',
|
|
},
|
|
title: 'Last Update Date Only',
|
|
},
|
|
lastUpdatedAt: new Date('1/1/2000').getTime() / 1000,
|
|
formattedLastUpdatedAt: 'Jan 1, 2000',
|
|
lastUpdatedBy: 'Author',
|
|
sidebarPosition: undefined,
|
|
tags: [],
|
|
});
|
|
});
|
|
|
|
it('docs with last_update front matter disabled', async () => {
|
|
const {siteDir, context, options, currentVersion, createTestUtilsPartial} =
|
|
await loadSite({
|
|
options: {
|
|
showLastUpdateAuthor: false,
|
|
showLastUpdateTime: false,
|
|
},
|
|
});
|
|
|
|
const testUtilsLocal = createTestUtilsPartial({
|
|
siteDir,
|
|
context,
|
|
options,
|
|
versionMetadata: currentVersion,
|
|
});
|
|
|
|
await testUtilsLocal.testMeta('customLastUpdate.md', {
|
|
version: 'current',
|
|
id: 'customLastUpdate',
|
|
unversionedId: 'customLastUpdate',
|
|
sourceDirName: '.',
|
|
permalink: '/docs/customLastUpdate',
|
|
slug: '/customLastUpdate',
|
|
title: 'Custom Last Update',
|
|
description: 'Custom last update',
|
|
frontMatter: {
|
|
last_update: {
|
|
author: 'Custom Author',
|
|
date: '1/1/2000',
|
|
},
|
|
title: 'Custom Last Update',
|
|
},
|
|
lastUpdatedAt: undefined,
|
|
formattedLastUpdatedAt: undefined,
|
|
lastUpdatedBy: undefined,
|
|
sidebarPosition: undefined,
|
|
tags: [],
|
|
});
|
|
});
|
|
|
|
it('docs with slugs', async () => {
|
|
const {defaultTestUtils} = await loadSite();
|
|
|
|
await defaultTestUtils.testSlug(
|
|
path.join('rootRelativeSlug.md'),
|
|
'/docs/rootRelativeSlug',
|
|
);
|
|
await defaultTestUtils.testSlug(
|
|
path.join('rootAbsoluteSlug.md'),
|
|
'/docs/rootAbsoluteSlug',
|
|
);
|
|
await defaultTestUtils.testSlug(
|
|
path.join('rootResolvedSlug.md'),
|
|
'/docs/hey/rootResolvedSlug',
|
|
);
|
|
await defaultTestUtils.testSlug(
|
|
path.join('rootTryToEscapeSlug.md'),
|
|
'/docs/rootTryToEscapeSlug',
|
|
);
|
|
|
|
await defaultTestUtils.testSlug(
|
|
path.join('slugs', 'absoluteSlug.md'),
|
|
'/docs/absoluteSlug',
|
|
);
|
|
await defaultTestUtils.testSlug(
|
|
path.join('slugs', 'relativeSlug.md'),
|
|
'/docs/slugs/relativeSlug',
|
|
);
|
|
await defaultTestUtils.testSlug(
|
|
path.join('slugs', 'resolvedSlug.md'),
|
|
'/docs/slugs/hey/resolvedSlug',
|
|
);
|
|
await defaultTestUtils.testSlug(
|
|
path.join('slugs', 'tryToEscapeSlug.md'),
|
|
'/docs/tryToEscapeSlug',
|
|
);
|
|
});
|
|
|
|
it('docs with invalid id', async () => {
|
|
const {defaultTestUtils} = await loadSite();
|
|
|
|
const error = await defaultTestUtils.getProcessDocFileError(
|
|
createFakeDocFile({
|
|
source: 'some/fake/path',
|
|
frontMatter: {
|
|
id: 'Hello/world',
|
|
},
|
|
}),
|
|
);
|
|
|
|
expect(error.message).toMatchInlineSnapshot(
|
|
`"Can't process doc metadata for doc at path path=some/fake/path in version name=current"`,
|
|
);
|
|
expect(error.cause).toBeDefined();
|
|
expect(error.cause!.message).toMatchInlineSnapshot(
|
|
`"Document id "Hello/world" cannot include slash."`,
|
|
);
|
|
});
|
|
|
|
it('custom pagination', async () => {
|
|
const {defaultTestUtils, options, versionsMetadata} = await loadSite();
|
|
const docs = await readVersionDocs(versionsMetadata[0]!, options);
|
|
await expect(
|
|
defaultTestUtils.generateNavigation(docs),
|
|
).resolves.toMatchSnapshot();
|
|
});
|
|
|
|
it('bad pagination', async () => {
|
|
const {defaultTestUtils, options, versionsMetadata} = await loadSite();
|
|
const docs = await readVersionDocs(versionsMetadata[0]!, options);
|
|
docs.push(
|
|
createFakeDocFile({
|
|
source: 'bad',
|
|
frontMatter: {pagination_prev: 'nonexistent'},
|
|
}),
|
|
);
|
|
await expect(
|
|
defaultTestUtils.generateNavigation(docs),
|
|
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
`"Error when loading bad in .: the pagination_prev front matter points to a non-existent ID nonexistent."`,
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('versioned site', () => {
|
|
async function loadSite(
|
|
loadSiteOptions: {options: Partial<PluginOptions>; locale?: string} = {
|
|
options: {},
|
|
},
|
|
) {
|
|
const siteDir = path.join(fixtureDir, 'versioned-site');
|
|
const context = await loadContext({
|
|
siteDir,
|
|
locale: loadSiteOptions.locale,
|
|
});
|
|
const options = {
|
|
id: DEFAULT_PLUGIN_ID,
|
|
...DEFAULT_OPTIONS,
|
|
...loadSiteOptions.options,
|
|
};
|
|
const versionsMetadata = await readVersionsMetadata({
|
|
context,
|
|
options,
|
|
});
|
|
expect(versionsMetadata).toHaveLength(4);
|
|
|
|
const currentVersion = versionsMetadata[0]!;
|
|
const version101 = versionsMetadata[1]!;
|
|
const version100 = versionsMetadata[2]!;
|
|
const versionWithSlugs = versionsMetadata[3]!;
|
|
|
|
const currentVersionTestUtils = createTestUtils({
|
|
siteDir,
|
|
context,
|
|
options,
|
|
versionMetadata: currentVersion,
|
|
});
|
|
const version101TestUtils = createTestUtils({
|
|
siteDir,
|
|
context,
|
|
options,
|
|
versionMetadata: version101,
|
|
});
|
|
|
|
const version100TestUtils = createTestUtils({
|
|
siteDir,
|
|
context,
|
|
options,
|
|
versionMetadata: version100,
|
|
});
|
|
|
|
const versionWithSlugsTestUtils = createTestUtils({
|
|
siteDir,
|
|
context,
|
|
options,
|
|
versionMetadata: versionWithSlugs,
|
|
});
|
|
|
|
return {
|
|
siteDir,
|
|
context,
|
|
options,
|
|
versionsMetadata,
|
|
currentVersionTestUtils,
|
|
version101TestUtils,
|
|
version100,
|
|
version100TestUtils,
|
|
versionWithSlugsTestUtils,
|
|
};
|
|
}
|
|
|
|
it('next docs', async () => {
|
|
const {currentVersionTestUtils} = await loadSite();
|
|
|
|
await currentVersionTestUtils.testMeta(path.join('foo', 'bar.md'), {
|
|
id: 'foo/bar',
|
|
version: 'current',
|
|
unversionedId: 'foo/bar',
|
|
sourceDirName: 'foo',
|
|
permalink: '/docs/next/foo/barSlug',
|
|
slug: '/foo/barSlug',
|
|
title: 'bar',
|
|
description: 'This is next version of bar.',
|
|
frontMatter: {
|
|
slug: 'barSlug',
|
|
tags: [
|
|
'barTag 1',
|
|
'barTag-2',
|
|
{
|
|
label: 'barTag 3',
|
|
permalink: 'barTag-3-permalink',
|
|
},
|
|
],
|
|
},
|
|
tags: [
|
|
{
|
|
label: 'barTag 1',
|
|
permalink: '/docs/next/tags/bar-tag-1',
|
|
},
|
|
{
|
|
label: 'barTag-2',
|
|
permalink: '/docs/next/tags/bar-tag-2',
|
|
},
|
|
{
|
|
label: 'barTag 3',
|
|
permalink: '/docs/next/tags/barTag-3-permalink',
|
|
},
|
|
],
|
|
});
|
|
await currentVersionTestUtils.testMeta(path.join('hello.md'), {
|
|
id: 'hello',
|
|
version: 'current',
|
|
unversionedId: 'hello',
|
|
sourceDirName: '.',
|
|
permalink: '/docs/next/',
|
|
slug: '/',
|
|
title: 'hello',
|
|
description: 'Hello next !',
|
|
frontMatter: {
|
|
slug: '/',
|
|
},
|
|
tags: [],
|
|
});
|
|
});
|
|
|
|
it('versioned docs', async () => {
|
|
const {version101TestUtils, version100TestUtils} = await loadSite();
|
|
|
|
await version100TestUtils.testMeta(path.join('foo', 'bar.md'), {
|
|
id: 'version-1.0.0/foo/bar',
|
|
unversionedId: 'foo/bar',
|
|
sourceDirName: 'foo',
|
|
permalink: '/docs/1.0.0/foo/barSlug',
|
|
slug: '/foo/barSlug',
|
|
title: 'bar',
|
|
description: 'Bar 1.0.0 !',
|
|
frontMatter: {slug: 'barSlug'},
|
|
version: '1.0.0',
|
|
tags: [],
|
|
});
|
|
await version100TestUtils.testMeta(path.join('hello.md'), {
|
|
id: 'version-1.0.0/hello',
|
|
unversionedId: 'hello',
|
|
sourceDirName: '.',
|
|
permalink: '/docs/1.0.0/',
|
|
slug: '/',
|
|
title: 'hello',
|
|
description: 'Hello 1.0.0 ! (translated en)',
|
|
frontMatter: {
|
|
slug: '/',
|
|
},
|
|
version: '1.0.0',
|
|
source:
|
|
'@site/i18n/en/docusaurus-plugin-content-docs/version-1.0.0/hello.md',
|
|
tags: [],
|
|
});
|
|
await version101TestUtils.testMeta(path.join('foo', 'bar.md'), {
|
|
id: 'version-1.0.1/foo/bar',
|
|
unversionedId: 'foo/bar',
|
|
sourceDirName: 'foo',
|
|
permalink: '/docs/foo/bar',
|
|
slug: '/foo/bar',
|
|
title: 'bar',
|
|
description: 'Bar 1.0.1 !',
|
|
version: '1.0.1',
|
|
frontMatter: {},
|
|
tags: [],
|
|
});
|
|
await version101TestUtils.testMeta(path.join('hello.md'), {
|
|
id: 'version-1.0.1/hello',
|
|
unversionedId: 'hello',
|
|
sourceDirName: '.',
|
|
permalink: '/docs/',
|
|
slug: '/',
|
|
title: 'hello',
|
|
description: 'Hello 1.0.1 !',
|
|
version: '1.0.1',
|
|
frontMatter: {
|
|
slug: '/',
|
|
},
|
|
tags: [],
|
|
});
|
|
});
|
|
|
|
it('next doc slugs', async () => {
|
|
const {currentVersionTestUtils} = await loadSite();
|
|
|
|
await currentVersionTestUtils.testSlug(
|
|
path.join('slugs', 'absoluteSlug.md'),
|
|
'/docs/next/absoluteSlug',
|
|
);
|
|
await currentVersionTestUtils.testSlug(
|
|
path.join('slugs', 'relativeSlug.md'),
|
|
'/docs/next/slugs/relativeSlug',
|
|
);
|
|
await currentVersionTestUtils.testSlug(
|
|
path.join('slugs', 'resolvedSlug.md'),
|
|
'/docs/next/slugs/hey/resolvedSlug',
|
|
);
|
|
await currentVersionTestUtils.testSlug(
|
|
path.join('slugs', 'tryToEscapeSlug.md'),
|
|
'/docs/next/tryToEscapeSlug',
|
|
);
|
|
});
|
|
|
|
it('versioned doc slugs', async () => {
|
|
const {versionWithSlugsTestUtils} = await loadSite();
|
|
|
|
await versionWithSlugsTestUtils.testSlug(
|
|
path.join('rootAbsoluteSlug.md'),
|
|
'/docs/withSlugs/rootAbsoluteSlug',
|
|
);
|
|
await versionWithSlugsTestUtils.testSlug(
|
|
path.join('rootRelativeSlug.md'),
|
|
'/docs/withSlugs/rootRelativeSlug',
|
|
);
|
|
await versionWithSlugsTestUtils.testSlug(
|
|
path.join('rootResolvedSlug.md'),
|
|
'/docs/withSlugs/hey/rootResolvedSlug',
|
|
);
|
|
await versionWithSlugsTestUtils.testSlug(
|
|
path.join('rootTryToEscapeSlug.md'),
|
|
'/docs/withSlugs/rootTryToEscapeSlug',
|
|
);
|
|
|
|
await versionWithSlugsTestUtils.testSlug(
|
|
path.join('slugs', 'absoluteSlug.md'),
|
|
'/docs/withSlugs/absoluteSlug',
|
|
);
|
|
await versionWithSlugsTestUtils.testSlug(
|
|
path.join('slugs', 'relativeSlug.md'),
|
|
'/docs/withSlugs/slugs/relativeSlug',
|
|
);
|
|
await versionWithSlugsTestUtils.testSlug(
|
|
path.join('slugs', 'resolvedSlug.md'),
|
|
'/docs/withSlugs/slugs/hey/resolvedSlug',
|
|
);
|
|
await versionWithSlugsTestUtils.testSlug(
|
|
path.join('slugs', 'tryToEscapeSlug.md'),
|
|
'/docs/withSlugs/tryToEscapeSlug',
|
|
);
|
|
});
|
|
|
|
it('doc with editUrl function', async () => {
|
|
const hardcodedEditUrl = 'hardcoded-edit-url';
|
|
|
|
const editUrlFunction: EditUrlFunction = jest.fn(() => hardcodedEditUrl);
|
|
|
|
const {siteDir, context, options, version100} = await loadSite({
|
|
options: {
|
|
editUrl: editUrlFunction,
|
|
},
|
|
});
|
|
|
|
const testUtilsLocal = createTestUtils({
|
|
siteDir,
|
|
context,
|
|
options,
|
|
versionMetadata: version100,
|
|
});
|
|
|
|
await testUtilsLocal.testMeta(path.join('hello.md'), {
|
|
id: 'version-1.0.0/hello',
|
|
unversionedId: 'hello',
|
|
sourceDirName: '.',
|
|
permalink: '/docs/1.0.0/',
|
|
slug: '/',
|
|
title: 'hello',
|
|
description: 'Hello 1.0.0 ! (translated en)',
|
|
frontMatter: {
|
|
slug: '/',
|
|
},
|
|
version: '1.0.0',
|
|
source:
|
|
'@site/i18n/en/docusaurus-plugin-content-docs/version-1.0.0/hello.md',
|
|
editUrl: hardcodedEditUrl,
|
|
tags: [],
|
|
});
|
|
|
|
expect(editUrlFunction).toHaveBeenCalledTimes(1);
|
|
expect(editUrlFunction).toHaveBeenCalledWith({
|
|
version: '1.0.0',
|
|
versionDocsDirPath: 'versioned_docs/version-1.0.0',
|
|
docPath: path.join('hello.md'),
|
|
permalink: '/docs/1.0.0/',
|
|
locale: 'en',
|
|
});
|
|
});
|
|
|
|
it('translated doc with editUrl', async () => {
|
|
const {siteDir, context, options, version100} = await loadSite({
|
|
options: {
|
|
editUrl: 'https://github.com/facebook/docusaurus/edit/main/website',
|
|
},
|
|
});
|
|
|
|
const testUtilsLocal = createTestUtils({
|
|
siteDir,
|
|
context,
|
|
options,
|
|
versionMetadata: version100,
|
|
});
|
|
|
|
await testUtilsLocal.testMeta(path.join('hello.md'), {
|
|
id: 'version-1.0.0/hello',
|
|
unversionedId: 'hello',
|
|
sourceDirName: '.',
|
|
permalink: '/docs/1.0.0/',
|
|
slug: '/',
|
|
title: 'hello',
|
|
description: 'Hello 1.0.0 ! (translated en)',
|
|
frontMatter: {
|
|
slug: '/',
|
|
},
|
|
version: '1.0.0',
|
|
source:
|
|
'@site/i18n/en/docusaurus-plugin-content-docs/version-1.0.0/hello.md',
|
|
editUrl:
|
|
'https://github.com/facebook/docusaurus/edit/main/website/versioned_docs/version-1.0.0/hello.md',
|
|
tags: [],
|
|
});
|
|
});
|
|
|
|
it('translated en doc with editUrl and editCurrentVersion=true', async () => {
|
|
const {siteDir, context, options, version100} = await loadSite({
|
|
options: {
|
|
editUrl: 'https://github.com/facebook/docusaurus/edit/main/website',
|
|
editCurrentVersion: true,
|
|
},
|
|
});
|
|
|
|
const testUtilsLocal = createTestUtils({
|
|
siteDir,
|
|
context,
|
|
options,
|
|
versionMetadata: version100,
|
|
});
|
|
|
|
await testUtilsLocal.testMeta(path.join('hello.md'), {
|
|
id: 'version-1.0.0/hello',
|
|
unversionedId: 'hello',
|
|
sourceDirName: '.',
|
|
permalink: '/docs/1.0.0/',
|
|
slug: '/',
|
|
title: 'hello',
|
|
description: 'Hello 1.0.0 ! (translated en)',
|
|
frontMatter: {
|
|
slug: '/',
|
|
},
|
|
version: '1.0.0',
|
|
source:
|
|
'@site/i18n/en/docusaurus-plugin-content-docs/version-1.0.0/hello.md',
|
|
editUrl:
|
|
'https://github.com/facebook/docusaurus/edit/main/website/docs/hello.md',
|
|
tags: [],
|
|
});
|
|
});
|
|
|
|
it('translated fr doc with editUrl and editLocalizedFiles=true', async () => {
|
|
const {siteDir, context, options, version100} = await loadSite({
|
|
options: {
|
|
editUrl: 'https://github.com/facebook/docusaurus/edit/main/website',
|
|
editLocalizedFiles: true,
|
|
},
|
|
locale: 'fr',
|
|
});
|
|
|
|
const testUtilsLocal = createTestUtils({
|
|
siteDir,
|
|
context,
|
|
options,
|
|
versionMetadata: version100,
|
|
});
|
|
|
|
await testUtilsLocal.testMeta(path.join('hello.md'), {
|
|
id: 'version-1.0.0/hello',
|
|
unversionedId: 'hello',
|
|
sourceDirName: '.',
|
|
permalink: '/fr/docs/1.0.0/',
|
|
slug: '/',
|
|
title: 'hello',
|
|
description: 'Hello 1.0.0 ! (translated fr)',
|
|
frontMatter: {
|
|
slug: '/',
|
|
},
|
|
version: '1.0.0',
|
|
source:
|
|
'@site/i18n/fr/docusaurus-plugin-content-docs/version-1.0.0/hello.md',
|
|
editUrl:
|
|
'https://github.com/facebook/docusaurus/edit/main/website/i18n/fr/docusaurus-plugin-content-docs/version-1.0.0/hello.md',
|
|
tags: [],
|
|
});
|
|
});
|
|
|
|
it('translated fr doc with editUrl and editLocalizedFiles=true + editCurrentVersion=true', async () => {
|
|
const {siteDir, context, options, version100} = await loadSite({
|
|
options: {
|
|
editUrl: 'https://github.com/facebook/docusaurus/edit/main/website',
|
|
editCurrentVersion: true,
|
|
editLocalizedFiles: true,
|
|
},
|
|
locale: 'fr',
|
|
});
|
|
|
|
const testUtilsLocal = createTestUtils({
|
|
siteDir,
|
|
context,
|
|
options,
|
|
versionMetadata: version100,
|
|
});
|
|
|
|
await testUtilsLocal.testMeta(path.join('hello.md'), {
|
|
id: 'version-1.0.0/hello',
|
|
unversionedId: 'hello',
|
|
sourceDirName: '.',
|
|
permalink: '/fr/docs/1.0.0/',
|
|
slug: '/',
|
|
title: 'hello',
|
|
description: 'Hello 1.0.0 ! (translated fr)',
|
|
frontMatter: {
|
|
slug: '/',
|
|
},
|
|
version: '1.0.0',
|
|
source:
|
|
'@site/i18n/fr/docusaurus-plugin-content-docs/version-1.0.0/hello.md',
|
|
editUrl:
|
|
'https://github.com/facebook/docusaurus/edit/main/website/i18n/fr/docusaurus-plugin-content-docs/current/hello.md',
|
|
tags: [],
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('isConventionalDocIndex', () => {
|
|
it('supports readme', () => {
|
|
expect(
|
|
isCategoryIndex({
|
|
fileName: 'readme',
|
|
directories: ['doesNotMatter'],
|
|
extension: '.md',
|
|
}),
|
|
).toBe(true);
|
|
expect(
|
|
isCategoryIndex({
|
|
fileName: 'readme',
|
|
directories: ['doesNotMatter'],
|
|
extension: '.mdx',
|
|
}),
|
|
).toBe(true);
|
|
expect(
|
|
isCategoryIndex({
|
|
fileName: 'README',
|
|
directories: ['doesNotMatter'],
|
|
extension: '.md',
|
|
}),
|
|
).toBe(true);
|
|
expect(
|
|
isCategoryIndex({
|
|
fileName: 'ReAdMe',
|
|
directories: ['doesNotMatter'],
|
|
extension: '',
|
|
}),
|
|
).toBe(true);
|
|
});
|
|
|
|
it('supports index', () => {
|
|
expect(
|
|
isCategoryIndex({
|
|
fileName: 'index',
|
|
directories: ['doesNotMatter'],
|
|
extension: '.md',
|
|
}),
|
|
).toBe(true);
|
|
expect(
|
|
isCategoryIndex({
|
|
fileName: 'index',
|
|
directories: ['doesNotMatter'],
|
|
extension: '.mdx',
|
|
}),
|
|
).toBe(true);
|
|
expect(
|
|
isCategoryIndex({
|
|
fileName: 'INDEX',
|
|
directories: ['doesNotMatter'],
|
|
extension: '.md',
|
|
}),
|
|
).toBe(true);
|
|
expect(
|
|
isCategoryIndex({
|
|
fileName: 'InDeX',
|
|
directories: ['doesNotMatter'],
|
|
extension: '',
|
|
}),
|
|
).toBe(true);
|
|
});
|
|
|
|
it('supports <categoryName>/<categoryName>.md', () => {
|
|
expect(
|
|
isCategoryIndex({
|
|
fileName: 'someCategory',
|
|
directories: ['someCategory', 'doesNotMatter'],
|
|
extension: '',
|
|
}),
|
|
).toBe(true);
|
|
expect(
|
|
isCategoryIndex({
|
|
fileName: 'someCategory',
|
|
directories: ['someCategory'],
|
|
extension: '.md',
|
|
}),
|
|
).toBe(true);
|
|
expect(
|
|
isCategoryIndex({
|
|
fileName: 'someCategory',
|
|
directories: ['someCategory'],
|
|
extension: '.mdx',
|
|
}),
|
|
).toBe(true);
|
|
expect(
|
|
isCategoryIndex({
|
|
fileName: 'SOME_CATEGORY',
|
|
directories: ['some_category'],
|
|
extension: '.md',
|
|
}),
|
|
).toBe(true);
|
|
expect(
|
|
isCategoryIndex({
|
|
fileName: 'some_category',
|
|
directories: ['some_category'],
|
|
extension: '',
|
|
}),
|
|
).toBe(true);
|
|
});
|
|
|
|
it('reject other cases', () => {
|
|
expect(
|
|
isCategoryIndex({
|
|
fileName: 'some_Category',
|
|
directories: ['someCategory'],
|
|
extension: '',
|
|
}),
|
|
).toBe(false);
|
|
expect(
|
|
isCategoryIndex({
|
|
fileName: 'read_me',
|
|
directories: ['doesNotMatter'],
|
|
extension: '',
|
|
}),
|
|
).toBe(false);
|
|
expect(
|
|
isCategoryIndex({
|
|
fileName: 'the index',
|
|
directories: ['doesNotMatter'],
|
|
extension: '',
|
|
}),
|
|
).toBe(false);
|
|
});
|
|
});
|