docusaurus/packages/docusaurus-plugin-content-docs/src/__tests__/docs.test.ts
Armano 2f53b1a895
refactor(v2): merge linkify function used in blog and docs and align properties (#4402)
* refactor(v2): merge linkify function used in blog and docs

* refactor(v2): rename docsDirPath and docsDirPathLocalized ad update types

* refactor(v2): rename blogPostsBySource and update types

* improve replaceMarkdownLinks api

Co-authored-by: slorber <lorber.sebastien@gmail.com>
2021-03-12 15:11:08 +01:00

808 lines
22 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 path from 'path';
import {loadContext} from '@docusaurus/core/src/server/index';
import {processDocMetadata, readVersionDocs, readDocFile} from '../docs';
import {readVersionsMetadata} from '../versions';
import {
DocFile,
DocMetadataBase,
MetadataOptions,
VersionMetadata,
PluginOptions,
EditUrlFunction,
} from '../types';
import {LoadContext} from '@docusaurus/types';
import {DEFAULT_PLUGIN_ID} from '@docusaurus/core/lib/constants';
import {DEFAULT_OPTIONS} from '../options';
import {Optional} from 'utility-types';
import {posixPath} from '@docusaurus/utils';
const fixtureDir = path.join(__dirname, '__fixtures__');
const createFakeDocFile = ({
source,
frontmatter = {},
markdown = 'some markdown content',
}: {
source: string;
frontmatter?: Record<string, string>;
markdown?: string;
}): DocFile => {
const content = `---
${Object.entries(frontmatter)
.map(([key, value]) => `${key}: ${value}`)
.join('\n')}
---
${markdown}
`;
return {
source,
content,
lastUpdate: {},
contentPath: 'docs',
filePath: source,
};
};
function createTestUtils({
siteDir,
context,
versionMetadata,
options,
}: {
siteDir: string;
context: LoadContext;
versionMetadata: VersionMetadata;
options: MetadataOptions;
}) {
async function readDoc(docFileSource: string) {
return readDocFile(versionMetadata, docFileSource, options);
}
function processDocFile(docFile: DocFile) {
return processDocMetadata({
docFile,
versionMetadata,
options,
context,
});
}
async function testMeta(
docFileSource: string,
expectedMetadata: Optional<
DocMetadataBase,
'source' | 'lastUpdatedBy' | 'lastUpdatedAt' | 'sidebar_label' | 'editUrl'
>,
) {
const docFile = await readDoc(docFileSource);
const metadata = await processDocMetadata({
docFile,
versionMetadata,
context,
options,
});
expect(metadata).toEqual({
lastUpdatedBy: undefined,
lastUpdatedAt: undefined,
sidebar_label: undefined,
editUrl: undefined,
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,
});
expect(metadata.permalink).toEqual(expectedPermalink);
}
return {processDocFile, testMeta, testSlug};
}
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 = readVersionsMetadata({
context,
options,
});
expect(versionsMetadata.length).toEqual(1);
const [currentVersion] = versionsMetadata;
const defaultTestUtils = createTestUtils({
siteDir,
context,
options,
versionMetadata: currentVersion,
});
return {
siteDir,
context,
options,
versionsMetadata,
defaultTestUtils,
currentVersion,
};
}
test('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',
'foo/bar.md',
'foo/baz.md',
'slugs/absoluteSlug.md',
'slugs/relativeSlug.md',
'slugs/resolvedSlug.md',
'slugs/tryToEscapeSlug.md',
].sort(),
);
});
test('normal docs', async () => {
const {defaultTestUtils} = await loadSite();
await defaultTestUtils.testMeta(path.join('foo', 'bar.md'), {
version: 'current',
id: 'foo/bar',
unversionedId: 'foo/bar',
isDocsHomePage: false,
permalink: '/docs/foo/bar',
slug: '/foo/bar',
title: 'Bar',
description: 'This is custom description',
});
await defaultTestUtils.testMeta(path.join('hello.md'), {
version: 'current',
id: 'hello',
unversionedId: 'hello',
isDocsHomePage: false,
permalink: '/docs/hello',
slug: '/hello',
title: 'Hello, World !',
description: `Hi, Endilie here :)`,
});
});
test('homePageId doc', async () => {
const {siteDir, context, options, currentVersion} = await loadSite({
options: {homePageId: 'hello'},
});
const testUtilsLocal = createTestUtils({
siteDir,
context,
options,
versionMetadata: currentVersion,
});
await testUtilsLocal.testMeta(path.join('hello.md'), {
version: 'current',
id: 'hello',
unversionedId: 'hello',
isDocsHomePage: true,
permalink: '/docs/',
slug: '/',
title: 'Hello, World !',
description: `Hi, Endilie here :)`,
});
});
test('homePageId doc nested', async () => {
const {siteDir, context, options, currentVersion} = await loadSite({
options: {homePageId: 'foo/bar'},
});
const testUtilsLocal = createTestUtils({
siteDir,
context,
options,
versionMetadata: currentVersion,
});
await testUtilsLocal.testMeta(path.join('foo', 'bar.md'), {
version: 'current',
id: 'foo/bar',
unversionedId: 'foo/bar',
isDocsHomePage: true,
permalink: '/docs/',
slug: '/',
title: 'Bar',
description: 'This is custom description',
});
});
test('docs with editUrl', async () => {
const {siteDir, context, options, currentVersion} = await loadSite({
options: {
editUrl: 'https://github.com/facebook/docusaurus/edit/master/website',
},
});
const testUtilsLocal = createTestUtils({
siteDir,
context,
options,
versionMetadata: currentVersion,
});
await testUtilsLocal.testMeta(path.join('foo', 'baz.md'), {
version: 'current',
id: 'foo/baz',
unversionedId: 'foo/baz',
isDocsHomePage: false,
permalink: '/docs/foo/bazSlug.html',
slug: '/foo/bazSlug.html',
title: 'baz',
editUrl:
'https://github.com/facebook/docusaurus/edit/master/website/docs/foo/baz.md',
description: 'Images',
});
});
test('docs with custom editUrl & unrelated frontmatter', async () => {
const {defaultTestUtils} = await loadSite();
await defaultTestUtils.testMeta('lorem.md', {
version: 'current',
id: 'lorem',
unversionedId: 'lorem',
isDocsHomePage: false,
permalink: '/docs/lorem',
slug: '/lorem',
title: 'lorem',
editUrl: 'https://github.com/customUrl/docs/lorem.md',
description: 'Lorem ipsum.',
});
});
test('docs with function editUrl', async () => {
const hardcodedEditUrl = 'hardcoded-edit-url';
const editUrlFunction: EditUrlFunction = jest.fn(() => hardcodedEditUrl);
const {siteDir, context, options, currentVersion} = await loadSite({
options: {
editUrl: editUrlFunction,
},
});
const testUtilsLocal = createTestUtils({
siteDir,
context,
options,
versionMetadata: currentVersion,
});
await testUtilsLocal.testMeta(path.join('foo', 'baz.md'), {
version: 'current',
id: 'foo/baz',
unversionedId: 'foo/baz',
isDocsHomePage: false,
permalink: '/docs/foo/bazSlug.html',
slug: '/foo/bazSlug.html',
title: 'baz',
editUrl: hardcodedEditUrl,
description: 'Images',
});
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',
});
});
test('docs with last update time and author', async () => {
const {siteDir, context, options, currentVersion} = await loadSite({
options: {
showLastUpdateAuthor: true,
showLastUpdateTime: true,
},
});
const testUtilsLocal = createTestUtils({
siteDir,
context,
options,
versionMetadata: currentVersion,
});
await testUtilsLocal.testMeta('lorem.md', {
version: 'current',
id: 'lorem',
unversionedId: 'lorem',
isDocsHomePage: false,
permalink: '/docs/lorem',
slug: '/lorem',
title: 'lorem',
editUrl: 'https://github.com/customUrl/docs/lorem.md',
description: 'Lorem ipsum.',
lastUpdatedAt: 1539502055,
formattedLastUpdatedAt: '10/14/2018',
lastUpdatedBy: 'Author',
});
});
test('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',
);
});
test('docs with invalid id', async () => {
const {defaultTestUtils} = await loadSite();
expect(() => {
defaultTestUtils.processDocFile(
createFakeDocFile({
source: 'some/fake/path',
frontmatter: {
id: 'Hello/world',
},
}),
);
}).toThrowErrorMatchingInlineSnapshot(
`"Document id [Hello/world] cannot include \\"/\\"."`,
);
});
test('docs with slug on doc home', async () => {
const {siteDir, context, options, currentVersion} = await loadSite({
options: {
homePageId: 'homePageId',
},
});
const testUtilsLocal = createTestUtils({
siteDir,
context,
options,
versionMetadata: currentVersion,
});
expect(() => {
testUtilsLocal.processDocFile(
createFakeDocFile({
source: 'homePageId',
frontmatter: {
slug: '/x/y',
},
}),
);
}).toThrowErrorMatchingInlineSnapshot(
`"The docs homepage (homePageId=homePageId) is not allowed to have a frontmatter slug=/x/y => you have to choose either homePageId or slug, not both"`,
);
});
});
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 = readVersionsMetadata({
context,
options,
});
expect(versionsMetadata.length).toEqual(4);
const [
currentVersion,
version101,
version100,
versionWithSlugs,
] = versionsMetadata;
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,
};
}
test('next docs', async () => {
const {currentVersionTestUtils} = await loadSite();
await currentVersionTestUtils.testMeta(path.join('foo', 'bar.md'), {
id: 'foo/bar',
unversionedId: 'foo/bar',
isDocsHomePage: false,
permalink: '/docs/next/foo/barSlug',
slug: '/foo/barSlug',
title: 'bar',
description: 'This is next version of bar.',
version: 'current',
});
await currentVersionTestUtils.testMeta(path.join('hello.md'), {
id: 'hello',
unversionedId: 'hello',
isDocsHomePage: false,
permalink: '/docs/next/hello',
slug: '/hello',
title: 'hello',
description: 'Hello next !',
version: 'current',
});
});
test('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',
isDocsHomePage: false,
permalink: '/docs/1.0.0/foo/barSlug',
slug: '/foo/barSlug',
title: 'bar',
description: 'Bar 1.0.0 !',
version: '1.0.0',
});
await version100TestUtils.testMeta(path.join('hello.md'), {
id: 'version-1.0.0/hello',
unversionedId: 'hello',
isDocsHomePage: false,
permalink: '/docs/1.0.0/hello',
slug: '/hello',
title: 'hello',
description: 'Hello 1.0.0 ! (translated en)',
version: '1.0.0',
source:
'@site/i18n/en/docusaurus-plugin-content-docs/version-1.0.0/hello.md',
});
await version101TestUtils.testMeta(path.join('foo', 'bar.md'), {
id: 'version-1.0.1/foo/bar',
unversionedId: 'foo/bar',
isDocsHomePage: false,
permalink: '/docs/foo/bar',
slug: '/foo/bar',
title: 'bar',
description: 'Bar 1.0.1 !',
version: '1.0.1',
});
await version101TestUtils.testMeta(path.join('hello.md'), {
id: 'version-1.0.1/hello',
unversionedId: 'hello',
isDocsHomePage: false,
permalink: '/docs/hello',
slug: '/hello',
title: 'hello',
description: 'Hello 1.0.1 !',
version: '1.0.1',
});
});
test('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',
);
});
test('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',
);
});
test('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',
isDocsHomePage: false,
permalink: '/docs/1.0.0/hello',
slug: '/hello',
title: 'hello',
description: 'Hello 1.0.0 ! (translated en)',
version: '1.0.0',
source:
'@site/i18n/en/docusaurus-plugin-content-docs/version-1.0.0/hello.md',
editUrl: hardcodedEditUrl,
});
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/hello',
locale: 'en',
});
});
test('translated doc with editUrl', async () => {
const {siteDir, context, options, version100} = await loadSite({
options: {
editUrl: 'https://github.com/facebook/docusaurus/edit/master/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',
isDocsHomePage: false,
permalink: '/docs/1.0.0/hello',
slug: '/hello',
title: 'hello',
description: 'Hello 1.0.0 ! (translated en)',
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/master/website/versioned_docs/version-1.0.0/hello.md',
});
});
test('translated en doc with editUrl and editCurrentVersion=true', async () => {
const {siteDir, context, options, version100} = await loadSite({
options: {
editUrl: 'https://github.com/facebook/docusaurus/edit/master/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',
isDocsHomePage: false,
permalink: '/docs/1.0.0/hello',
slug: '/hello',
title: 'hello',
description: 'Hello 1.0.0 ! (translated en)',
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/master/website/docs/hello.md',
});
});
test('translated fr doc with editUrl and editLocalizedFiles=true', async () => {
const {siteDir, context, options, version100} = await loadSite({
options: {
editUrl: 'https://github.com/facebook/docusaurus/edit/master/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',
isDocsHomePage: false,
permalink: '/fr/docs/1.0.0/hello',
slug: '/hello',
title: 'hello',
description: 'Hello 1.0.0 ! (translated fr)',
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/master/website/i18n/fr/docusaurus-plugin-content-docs/version-1.0.0/hello.md',
});
});
test('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/master/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',
isDocsHomePage: false,
permalink: '/fr/docs/1.0.0/hello',
slug: '/hello',
title: 'hello',
description: 'Hello 1.0.0 ! (translated fr)',
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/master/website/i18n/fr/docusaurus-plugin-content-docs/current/hello.md',
});
});
});