docusaurus/packages/docusaurus-plugin-content-docs/src/__tests__/docs.test.ts
2022-10-28 11:46:54 +02:00

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);
});
});