mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-10 15:47:23 +02:00
* make number prefix parsing logic configurable * Make numberPrefixParser configurable + rename frontmatter + avoid parsing date/version patterns by default * add more tests * more test cases
336 lines
8.9 KiB
TypeScript
336 lines
8.9 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 {
|
|
CategoryMetadatasFile,
|
|
DefaultSidebarItemsGenerator,
|
|
} from '../sidebarItemsGenerator';
|
|
import {DefaultCategoryCollapsedValue} from '../sidebars';
|
|
import {Sidebar, SidebarItemsGenerator} from '../types';
|
|
import fs from 'fs-extra';
|
|
import {DefaultNumberPrefixParser} from '../numberPrefix';
|
|
|
|
describe('DefaultSidebarItemsGenerator', () => {
|
|
function testDefaultSidebarItemsGenerator(
|
|
options: Partial<Parameters<SidebarItemsGenerator>[0]>,
|
|
) {
|
|
return DefaultSidebarItemsGenerator({
|
|
numberPrefixParser: DefaultNumberPrefixParser,
|
|
item: {
|
|
type: 'autogenerated',
|
|
dirName: '.',
|
|
},
|
|
version: {
|
|
versionName: 'current',
|
|
contentPath: 'docs',
|
|
},
|
|
docs: [],
|
|
...options,
|
|
});
|
|
}
|
|
|
|
function mockCategoryMetadataFiles(
|
|
categoryMetadataFiles: Record<string, Partial<CategoryMetadatasFile>>,
|
|
) {
|
|
jest.spyOn(fs, 'pathExists').mockImplementation((metadataFilePath) => {
|
|
return typeof categoryMetadataFiles[metadataFilePath] !== 'undefined';
|
|
});
|
|
jest.spyOn(fs, 'readFile').mockImplementation(
|
|
// @ts-expect-error: annoying TS error due to overrides
|
|
async (metadataFilePath: string) => {
|
|
return JSON.stringify(categoryMetadataFiles[metadataFilePath]);
|
|
},
|
|
);
|
|
}
|
|
|
|
test('generates empty sidebar slice when no docs and emit a warning', async () => {
|
|
const consoleWarn = jest.spyOn(console, 'warn');
|
|
const sidebarSlice = await testDefaultSidebarItemsGenerator({
|
|
docs: [],
|
|
});
|
|
expect(sidebarSlice).toEqual([]);
|
|
expect(consoleWarn).toHaveBeenCalledWith(
|
|
expect.stringMatching(
|
|
/No docs found in dir .: can't auto-generate a sidebar/,
|
|
),
|
|
);
|
|
});
|
|
|
|
test('generates simple flat sidebar', async () => {
|
|
const sidebarSlice = await DefaultSidebarItemsGenerator({
|
|
numberPrefixParser: DefaultNumberPrefixParser,
|
|
item: {
|
|
type: 'autogenerated',
|
|
dirName: '.',
|
|
},
|
|
version: {
|
|
versionName: 'current',
|
|
contentPath: '',
|
|
},
|
|
docs: [
|
|
{
|
|
id: 'doc1',
|
|
source: 'doc1.md',
|
|
sourceDirName: '.',
|
|
sidebarPosition: 2,
|
|
frontMatter: {
|
|
sidebar_label: 'doc1 sidebar label',
|
|
},
|
|
},
|
|
{
|
|
id: 'doc2',
|
|
source: 'doc2.md',
|
|
sourceDirName: '.',
|
|
sidebarPosition: 3,
|
|
frontMatter: {},
|
|
},
|
|
{
|
|
id: 'doc3',
|
|
source: 'doc3.md',
|
|
sourceDirName: '.',
|
|
sidebarPosition: 1,
|
|
frontMatter: {},
|
|
},
|
|
{
|
|
id: 'doc4',
|
|
source: 'doc4.md',
|
|
sourceDirName: '.',
|
|
sidebarPosition: 1.5,
|
|
frontMatter: {},
|
|
},
|
|
{
|
|
id: 'doc5',
|
|
source: 'doc5.md',
|
|
sourceDirName: '.',
|
|
sidebarPosition: undefined,
|
|
frontMatter: {},
|
|
},
|
|
],
|
|
});
|
|
|
|
expect(sidebarSlice).toEqual([
|
|
{type: 'doc', id: 'doc3'},
|
|
{type: 'doc', id: 'doc4'},
|
|
{type: 'doc', id: 'doc1', label: 'doc1 sidebar label'},
|
|
{type: 'doc', id: 'doc2'},
|
|
{type: 'doc', id: 'doc5'},
|
|
] as Sidebar);
|
|
});
|
|
|
|
test('generates complex nested sidebar', async () => {
|
|
mockCategoryMetadataFiles({
|
|
'02-Guides/_category_.json': {collapsed: false},
|
|
'02-Guides/01-SubGuides/_category_.yml': {
|
|
label: 'SubGuides (metadata file label)',
|
|
},
|
|
});
|
|
|
|
const sidebarSlice = await DefaultSidebarItemsGenerator({
|
|
numberPrefixParser: DefaultNumberPrefixParser,
|
|
item: {
|
|
type: 'autogenerated',
|
|
dirName: '.',
|
|
},
|
|
version: {
|
|
versionName: 'current',
|
|
contentPath: '',
|
|
},
|
|
docs: [
|
|
{
|
|
id: 'intro',
|
|
source: 'intro.md',
|
|
sourceDirName: '.',
|
|
sidebarPosition: 1,
|
|
frontMatter: {},
|
|
},
|
|
{
|
|
id: 'tutorial2',
|
|
source: 'tutorial2.md',
|
|
sourceDirName: '01-Tutorials',
|
|
sidebarPosition: 2,
|
|
frontMatter: {},
|
|
},
|
|
{
|
|
id: 'tutorial1',
|
|
source: 'tutorial1.md',
|
|
sourceDirName: '01-Tutorials',
|
|
sidebarPosition: 1,
|
|
frontMatter: {},
|
|
},
|
|
{
|
|
id: 'guide2',
|
|
source: 'guide2.md',
|
|
sourceDirName: '02-Guides',
|
|
sidebarPosition: 2,
|
|
frontMatter: {},
|
|
},
|
|
{
|
|
id: 'guide1',
|
|
source: 'guide1.md',
|
|
sourceDirName: '02-Guides',
|
|
sidebarPosition: 1,
|
|
frontMatter: {},
|
|
},
|
|
{
|
|
id: 'nested-guide',
|
|
source: 'nested-guide.md',
|
|
sourceDirName: '02-Guides/01-SubGuides',
|
|
sidebarPosition: undefined,
|
|
frontMatter: {},
|
|
},
|
|
{
|
|
id: 'end',
|
|
source: 'end.md',
|
|
sourceDirName: '.',
|
|
sidebarPosition: 3,
|
|
frontMatter: {},
|
|
},
|
|
],
|
|
});
|
|
|
|
expect(sidebarSlice).toEqual([
|
|
{type: 'doc', id: 'intro'},
|
|
{
|
|
type: 'category',
|
|
label: 'Tutorials',
|
|
collapsed: DefaultCategoryCollapsedValue,
|
|
items: [
|
|
{type: 'doc', id: 'tutorial1'},
|
|
{type: 'doc', id: 'tutorial2'},
|
|
],
|
|
},
|
|
{
|
|
type: 'category',
|
|
label: 'Guides',
|
|
collapsed: false,
|
|
items: [
|
|
{type: 'doc', id: 'guide1'},
|
|
{
|
|
type: 'category',
|
|
label: 'SubGuides (metadata file label)',
|
|
collapsed: DefaultCategoryCollapsedValue,
|
|
items: [{type: 'doc', id: 'nested-guide'}],
|
|
},
|
|
{type: 'doc', id: 'guide2'},
|
|
],
|
|
},
|
|
{type: 'doc', id: 'end'},
|
|
] as Sidebar);
|
|
});
|
|
|
|
test('generates subfolder sidebar', async () => {
|
|
// Ensure that category metadata file is correctly read
|
|
// fix edge case found in https://github.com/facebook/docusaurus/issues/4638
|
|
mockCategoryMetadataFiles({
|
|
'subfolder/subsubfolder/subsubsubfolder2/_category_.yml': {
|
|
position: 2,
|
|
label: 'subsubsubfolder2 (_category_.yml label)',
|
|
},
|
|
'subfolder/subsubfolder/subsubsubfolder3/_category_.json': {
|
|
position: 1,
|
|
label: 'subsubsubfolder3 (_category_.json label)',
|
|
collapsed: false,
|
|
},
|
|
});
|
|
|
|
const sidebarSlice = await DefaultSidebarItemsGenerator({
|
|
numberPrefixParser: DefaultNumberPrefixParser,
|
|
item: {
|
|
type: 'autogenerated',
|
|
dirName: 'subfolder/subsubfolder',
|
|
},
|
|
version: {
|
|
versionName: 'current',
|
|
contentPath: '',
|
|
},
|
|
docs: [
|
|
{
|
|
id: 'doc1',
|
|
source: 'doc1.md',
|
|
sourceDirName: 'subfolder/subsubfolder',
|
|
sidebarPosition: undefined,
|
|
frontMatter: {},
|
|
},
|
|
{
|
|
id: 'doc2',
|
|
source: 'doc2.md',
|
|
sourceDirName: 'subfolder',
|
|
sidebarPosition: undefined,
|
|
frontMatter: {},
|
|
},
|
|
{
|
|
id: 'doc3',
|
|
source: 'doc3.md',
|
|
sourceDirName: '.',
|
|
sidebarPosition: undefined,
|
|
frontMatter: {},
|
|
},
|
|
{
|
|
id: 'doc4',
|
|
source: 'doc4.md',
|
|
sourceDirName: 'subfolder/subsubfolder',
|
|
sidebarPosition: undefined,
|
|
frontMatter: {},
|
|
},
|
|
{
|
|
id: 'doc5',
|
|
source: 'doc5.md',
|
|
sourceDirName: 'subfolder/subsubfolder/subsubsubfolder',
|
|
sidebarPosition: undefined,
|
|
frontMatter: {},
|
|
},
|
|
{
|
|
id: 'doc6',
|
|
source: 'doc6.md',
|
|
sourceDirName: 'subfolder/subsubfolder/subsubsubfolder2',
|
|
sidebarPosition: undefined,
|
|
frontMatter: {},
|
|
},
|
|
{
|
|
id: 'doc7',
|
|
source: 'doc7.md',
|
|
sourceDirName: 'subfolder/subsubfolder/subsubsubfolder3',
|
|
sidebarPosition: 2,
|
|
frontMatter: {},
|
|
},
|
|
{
|
|
id: 'doc8',
|
|
source: 'doc8.md',
|
|
sourceDirName: 'subfolder/subsubfolder/subsubsubfolder3',
|
|
sidebarPosition: 1,
|
|
frontMatter: {},
|
|
},
|
|
],
|
|
});
|
|
|
|
expect(sidebarSlice).toEqual([
|
|
{
|
|
type: 'category',
|
|
label: 'subsubsubfolder3 (_category_.json label)',
|
|
collapsed: false,
|
|
items: [
|
|
{type: 'doc', id: 'doc8'},
|
|
{type: 'doc', id: 'doc7'},
|
|
],
|
|
},
|
|
{
|
|
type: 'category',
|
|
label: 'subsubsubfolder2 (_category_.yml label)',
|
|
collapsed: true,
|
|
items: [{type: 'doc', id: 'doc6'}],
|
|
},
|
|
{type: 'doc', id: 'doc1'},
|
|
{type: 'doc', id: 'doc4'},
|
|
{
|
|
type: 'category',
|
|
label: 'subsubsubfolder',
|
|
collapsed: true,
|
|
items: [{type: 'doc', id: 'doc5'}],
|
|
},
|
|
] as Sidebar);
|
|
});
|
|
});
|