mirror of
https://github.com/facebook/docusaurus.git
synced 2025-04-29 02:08:36 +02:00
fix(v2): docs plugin stability improvement (100% test coverage) (#1912)
* update jest config * add more tests on docs plugin * fix(v2): docs plugin should not add routes if there are no docs * fix * rm -rf coverage * nits * update
This commit is contained in:
parent
ad22c9fab4
commit
a8826b98b3
26 changed files with 464 additions and 71 deletions
|
@ -14,6 +14,7 @@
|
||||||
- Prioritize `@docusaurus/core` dependencies/ node_modules over user's node_modules. This fix a bug whereby if user has core-js@3 on its own node_modules but docusaurus depends on core-js@2, we previously encounter `Module not found: core-js/modules/xxxx` (because core-js@3 doesn't have that).
|
- Prioritize `@docusaurus/core` dependencies/ node_modules over user's node_modules. This fix a bug whereby if user has core-js@3 on its own node_modules but docusaurus depends on core-js@2, we previously encounter `Module not found: core-js/modules/xxxx` (because core-js@3 doesn't have that).
|
||||||
Another example is if user installed webpack@3 but docusaurus depends on webpack@4.
|
Another example is if user installed webpack@3 but docusaurus depends on webpack@4.
|
||||||
- Added code block line highlighting feature (thanks @lex111)! If you have previously swizzled the `CodeBlock` theme component, it is recommended to update your source code to have this feature.
|
- Added code block line highlighting feature (thanks @lex111)! If you have previously swizzled the `CodeBlock` theme component, it is recommended to update your source code to have this feature.
|
||||||
|
- Fix a bug where docs plugin add `/docs` route even if docs folder is empty. We also improved docs plugin test coverage to 100% for stability before working on docs versioning.
|
||||||
|
|
||||||
## 2.0.0-alpha.31
|
## 2.0.0-alpha.31
|
||||||
|
|
||||||
|
|
|
@ -7,20 +7,23 @@
|
||||||
|
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
|
const ignorePatterns = [
|
||||||
|
'/node_modules/',
|
||||||
|
'__fixtures__',
|
||||||
|
'/packages/docusaurus/lib',
|
||||||
|
'/packages/docusaurus-utils/lib',
|
||||||
|
'/packages/docusaurus-plugin-content-blog/lib',
|
||||||
|
'/packages/docusaurus-plugin-content-docs/lib',
|
||||||
|
'/packages/docusaurus-plugin-content-pages/lib',
|
||||||
|
];
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
rootDir: path.resolve(__dirname),
|
rootDir: path.resolve(__dirname),
|
||||||
verbose: true,
|
verbose: true,
|
||||||
testURL: 'http://localhost/',
|
testURL: 'http://localhost/',
|
||||||
testEnvironment: 'node',
|
testEnvironment: 'node',
|
||||||
testPathIgnorePatterns: [
|
testPathIgnorePatterns: ignorePatterns,
|
||||||
'/node_modules/',
|
coveragePathIgnorePatterns: ignorePatterns,
|
||||||
'__fixtures__',
|
|
||||||
'/packages/docusaurus/lib',
|
|
||||||
'/packages/docusaurus-utils/lib',
|
|
||||||
'/packages/docusaurus-plugin-content-blog/lib',
|
|
||||||
'/packages/docusaurus-plugin-content-docs-legacy/lib',
|
|
||||||
'/packages/docusaurus-plugin-content-pages/lib',
|
|
||||||
],
|
|
||||||
transform: {
|
transform: {
|
||||||
'^.+\\.[jt]sx?$': 'babel-jest',
|
'^.+\\.[jt]sx?$': 'babel-jest',
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
id: hello/super
|
||||||
|
---
|
||||||
|
|
||||||
|
Lorem
|
|
@ -0,0 +1,16 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2017-present, Facebook, Inc.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
title: 'My Site',
|
||||||
|
tagline: 'The tagline of my site',
|
||||||
|
url: 'https://your-docusaurus-test-site.com',
|
||||||
|
baseUrl: '/',
|
||||||
|
favicon: 'img/favicon.ico',
|
||||||
|
organizationName: 'facebook', // Usually your GitHub org/user name.
|
||||||
|
projectName: 'docusaurus', // Usually your repo name.
|
||||||
|
};
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"docs": {
|
||||||
|
"Test": [
|
||||||
|
{
|
||||||
|
"type": "category",
|
||||||
|
"label": "Category Label",
|
||||||
|
"items": "doc1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"docs": {
|
||||||
|
"Test": [
|
||||||
|
"foo/bar",
|
||||||
|
"foo/baz",
|
||||||
|
{
|
||||||
|
"type": "category",
|
||||||
|
"label": "category",
|
||||||
|
"href": "https://github.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ref",
|
||||||
|
"id": "hello"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Guides": [
|
||||||
|
"hello"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,4 @@
|
||||||
---
|
---
|
||||||
id: lorem
|
|
||||||
custom_edit_url: https://github.com/customUrl/docs/lorem.md
|
custom_edit_url: https://github.com/customUrl/docs/lorem.md
|
||||||
---
|
---
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2017-present, Facebook, Inc.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
title: 'My Site',
|
||||||
|
tagline: 'The tagline of my site',
|
||||||
|
url: 'https://your-docusaurus-test-site.com',
|
||||||
|
baseUrl: '/',
|
||||||
|
favicon: 'img/favicon.ico',
|
||||||
|
organizationName: 'facebook', // Usually your GitHub org/user name.
|
||||||
|
projectName: 'docusaurus', // Usually your repo name.
|
||||||
|
};
|
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"docs": {
|
||||||
|
"Test": [
|
||||||
|
{
|
||||||
|
"type": "category",
|
||||||
|
"label": "foo",
|
||||||
|
"items": ["foo/bar", "foo/baz"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "link",
|
||||||
|
"label": "Github",
|
||||||
|
"href": "https://github.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ref",
|
||||||
|
"id": "hello"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Guides": [
|
||||||
|
"hello"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"docs": {
|
||||||
|
"Test": [
|
||||||
|
"goku"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,110 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`simple website content 1`] = `
|
||||||
|
Object {
|
||||||
|
"docs": Array [
|
||||||
|
Object {
|
||||||
|
"items": Array [
|
||||||
|
Object {
|
||||||
|
"items": Array [
|
||||||
|
Object {
|
||||||
|
"href": "/docs/foo/bar",
|
||||||
|
"label": "Bar",
|
||||||
|
"type": "link",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"href": "/docs/foo/baz",
|
||||||
|
"label": "baz",
|
||||||
|
"type": "link",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"label": "foo",
|
||||||
|
"type": "category",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"href": "https://github.com",
|
||||||
|
"label": "Github",
|
||||||
|
"type": "link",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"href": "/docs/hello",
|
||||||
|
"label": "Hello, World !",
|
||||||
|
"type": "link",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"label": "Test",
|
||||||
|
"type": "category",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"items": Array [
|
||||||
|
Object {
|
||||||
|
"href": "/docs/hello",
|
||||||
|
"label": "Hello, World !",
|
||||||
|
"type": "link",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"label": "Guides",
|
||||||
|
"type": "category",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`simple website content 2`] = `
|
||||||
|
Array [
|
||||||
|
Object {
|
||||||
|
"component": "@theme/DocPage",
|
||||||
|
"modules": Object {
|
||||||
|
"docsMetadata": "@docusaurus-plugin-content-docs/docs-b5f.json",
|
||||||
|
},
|
||||||
|
"path": "/docs",
|
||||||
|
"routes": Array [
|
||||||
|
Object {
|
||||||
|
"component": "@theme/DocItem",
|
||||||
|
"exact": true,
|
||||||
|
"modules": Object {
|
||||||
|
"content": "@site/docs/permalink.md",
|
||||||
|
"metadata": "@docusaurus-plugin-content-docs/docs-endiliey-permalink-086.json",
|
||||||
|
},
|
||||||
|
"path": "/docs/endiliey/permalink",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"component": "@theme/DocItem",
|
||||||
|
"exact": true,
|
||||||
|
"modules": Object {
|
||||||
|
"content": "@site/docs/foo/bar.md",
|
||||||
|
"metadata": "@docusaurus-plugin-content-docs/docs-foo-bar-cef.json",
|
||||||
|
},
|
||||||
|
"path": "/docs/foo/bar",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"component": "@theme/DocItem",
|
||||||
|
"exact": true,
|
||||||
|
"modules": Object {
|
||||||
|
"content": "@site/docs/foo/baz.md",
|
||||||
|
"metadata": "@docusaurus-plugin-content-docs/docs-foo-baz-dd9.json",
|
||||||
|
},
|
||||||
|
"path": "/docs/foo/baz",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"component": "@theme/DocItem",
|
||||||
|
"exact": true,
|
||||||
|
"modules": Object {
|
||||||
|
"content": "@site/docs/hello.md",
|
||||||
|
"metadata": "@docusaurus-plugin-content-docs/docs-hello-da2.json",
|
||||||
|
},
|
||||||
|
"path": "/docs/hello",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"component": "@theme/DocItem",
|
||||||
|
"exact": true,
|
||||||
|
"modules": Object {
|
||||||
|
"content": "@site/docs/lorem.md",
|
||||||
|
"metadata": "@docusaurus-plugin-content-docs/docs-lorem-17b.json",
|
||||||
|
},
|
||||||
|
"path": "/docs/lorem",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
`;
|
|
@ -6,32 +6,109 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
import {validate} from 'webpack';
|
||||||
|
import fs from 'fs-extra';
|
||||||
import pluginContentDocs from '../index';
|
import pluginContentDocs from '../index';
|
||||||
import {LoadContext} from '@docusaurus/types';
|
import {loadContext} from '@docusaurus/core/src/server/index';
|
||||||
|
import {applyConfigureWebpack} from '@docusaurus/core/src/webpack/utils';
|
||||||
|
import {RouteConfig} from '@docusaurus/types';
|
||||||
|
|
||||||
describe('loadDocs', () => {
|
const createFakeActions = (routeConfigs: RouteConfig[], contentDir) => {
|
||||||
test('simple website', async () => {
|
return {
|
||||||
const siteDir = path.join(__dirname, '__fixtures__', 'website');
|
addRoute: (config: RouteConfig) => {
|
||||||
const generatedFilesDir: string = path.resolve(siteDir, '.docusaurus');
|
config.routes.sort((a, b) =>
|
||||||
const siteConfig = {
|
a.path > b.path ? 1 : b.path > a.path ? -1 : 0,
|
||||||
title: 'Hello',
|
);
|
||||||
baseUrl: '/',
|
routeConfigs.push(config);
|
||||||
url: 'https://docusaurus.io',
|
},
|
||||||
};
|
createData: async (name, _content) => {
|
||||||
const context = {
|
return path.join(contentDir, name);
|
||||||
siteDir,
|
},
|
||||||
siteConfig,
|
};
|
||||||
generatedFilesDir,
|
};
|
||||||
} as LoadContext;
|
|
||||||
const sidebarPath = path.join(siteDir, 'sidebars.json');
|
test('site with wrong sidebar file', async () => {
|
||||||
const pluginPath = 'docs';
|
const siteDir = path.join(__dirname, '__fixtures__', 'simple-site');
|
||||||
const plugin = pluginContentDocs(context, {
|
const context = loadContext(siteDir);
|
||||||
path: pluginPath,
|
const sidebarPath = path.join(siteDir, 'wrong-sidebars.json');
|
||||||
sidebarPath,
|
const plugin = pluginContentDocs(context, {
|
||||||
|
sidebarPath,
|
||||||
|
});
|
||||||
|
return plugin
|
||||||
|
.loadContent()
|
||||||
|
.catch(e =>
|
||||||
|
expect(e).toMatchInlineSnapshot(
|
||||||
|
`[Error: Improper sidebars file, document with id 'goku' not found.]`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('empty/no docs website', () => {
|
||||||
|
const siteDir = path.join(__dirname, '__fixtures__', 'empty-site');
|
||||||
|
const context = loadContext(siteDir);
|
||||||
|
|
||||||
|
test('no files in docs folder', async () => {
|
||||||
|
await fs.ensureDir(path.join(siteDir, 'docs'));
|
||||||
|
const plugin = pluginContentDocs(context, {});
|
||||||
|
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);
|
||||||
|
|
||||||
|
await plugin.contentLoaded({
|
||||||
|
content,
|
||||||
|
actions,
|
||||||
});
|
});
|
||||||
const {docsMetadata} = await plugin.loadContent();
|
|
||||||
|
|
||||||
|
expect(routeConfigs).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('docs folder does not exist', async () => {
|
||||||
|
const plugin = pluginContentDocs(context, {path: '/path/does/not/exist/'});
|
||||||
|
const content = await plugin.loadContent();
|
||||||
|
expect(content).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('simple website', () => {
|
||||||
|
const siteDir = path.join(__dirname, '__fixtures__', 'simple-site');
|
||||||
|
const context = loadContext(siteDir);
|
||||||
|
const sidebarPath = path.join(siteDir, 'sidebars.json');
|
||||||
|
const pluginPath = 'docs';
|
||||||
|
const plugin = pluginContentDocs(context, {
|
||||||
|
path: pluginPath,
|
||||||
|
sidebarPath,
|
||||||
|
});
|
||||||
|
const pluginContentDir = path.join(context.generatedFilesDir, plugin.name);
|
||||||
|
|
||||||
|
test('getPathToWatch', () => {
|
||||||
|
const pathToWatch = plugin.getPathsToWatch();
|
||||||
|
expect(pathToWatch).not.toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('configureWebpack', async () => {
|
||||||
|
const config = applyConfigureWebpack(
|
||||||
|
plugin.configureWebpack,
|
||||||
|
{
|
||||||
|
entry: './src/index.js',
|
||||||
|
output: {
|
||||||
|
filename: 'main.js',
|
||||||
|
path: path.resolve(__dirname, 'dist'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
const errors = validate(config);
|
||||||
|
expect(errors.length).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('content', async () => {
|
||||||
|
const content = await plugin.loadContent();
|
||||||
|
const {docsMetadata, docsSidebars} = content;
|
||||||
expect(docsMetadata.hello).toEqual({
|
expect(docsMetadata.hello).toEqual({
|
||||||
id: 'hello',
|
id: 'hello',
|
||||||
permalink: '/docs/hello',
|
permalink: '/docs/hello',
|
||||||
|
@ -57,5 +134,18 @@ describe('loadDocs', () => {
|
||||||
title: 'Bar',
|
title: 'Bar',
|
||||||
description: 'This is custom description',
|
description: 'This is custom description',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
expect(docsSidebars).toMatchSnapshot();
|
||||||
|
|
||||||
|
const routeConfigs = [];
|
||||||
|
const actions = createFakeActions(routeConfigs, pluginContentDir);
|
||||||
|
|
||||||
|
await plugin.contentLoaded({
|
||||||
|
content,
|
||||||
|
actions,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(routeConfigs).not.toEqual([]);
|
||||||
|
expect(routeConfigs).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,15 +7,17 @@
|
||||||
|
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
import shell from 'shelljs';
|
||||||
|
import spawn from 'cross-spawn';
|
||||||
|
|
||||||
import lastUpdate from '../lastUpdate';
|
import lastUpdate from '../lastUpdate';
|
||||||
|
|
||||||
describe('lastUpdate', () => {
|
describe('lastUpdate', () => {
|
||||||
|
const existingFilePath = path.join(
|
||||||
|
__dirname,
|
||||||
|
'__fixtures__/simple-site/docs/hello.md',
|
||||||
|
);
|
||||||
test('existing test file in repository with Git timestamp', () => {
|
test('existing test file in repository with Git timestamp', () => {
|
||||||
const existingFilePath = path.join(
|
|
||||||
__dirname,
|
|
||||||
'__fixtures__/website/docs/hello.md',
|
|
||||||
);
|
|
||||||
const lastUpdateData = lastUpdate(existingFilePath);
|
const lastUpdateData = lastUpdate(existingFilePath);
|
||||||
expect(lastUpdateData).not.toBeNull();
|
expect(lastUpdateData).not.toBeNull();
|
||||||
|
|
||||||
|
@ -44,4 +46,30 @@ describe('lastUpdate', () => {
|
||||||
expect(lastUpdate(tempFilePath)).toBeNull();
|
expect(lastUpdate(tempFilePath)).toBeNull();
|
||||||
fs.unlinkSync(tempFilePath);
|
fs.unlinkSync(tempFilePath);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Git does not exist', () => {
|
||||||
|
const mock = jest.spyOn(shell, 'which').mockImplementationOnce(() => null);
|
||||||
|
const consoleMock = jest.spyOn(console, 'warn').mockImplementation();
|
||||||
|
const lastUpdateData = lastUpdate(existingFilePath);
|
||||||
|
expect(lastUpdateData).toBeNull();
|
||||||
|
expect(consoleMock).toHaveBeenLastCalledWith(
|
||||||
|
'Sorry, the docs plugin last update options require Git.',
|
||||||
|
);
|
||||||
|
|
||||||
|
consoleMock.mockRestore();
|
||||||
|
mock.mockRestore();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Error', () => {
|
||||||
|
const mock = jest.spyOn(spawn, 'sync').mockImplementationOnce(() => {
|
||||||
|
throw new Error('PERMISSION Error');
|
||||||
|
});
|
||||||
|
const consoleMock = jest.spyOn(console, 'error').mockImplementation();
|
||||||
|
const lastUpdateData = lastUpdate('/fake/path/');
|
||||||
|
expect(lastUpdateData).toBeNull();
|
||||||
|
expect(consoleMock).toHaveBeenLastCalledWith(new Error('PERMISSION Error'));
|
||||||
|
|
||||||
|
consoleMock.mockRestore();
|
||||||
|
mock.mockRestore();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,14 +9,15 @@ import path from 'path';
|
||||||
import processMetadata from '../metadata';
|
import processMetadata from '../metadata';
|
||||||
|
|
||||||
describe('processMetadata', () => {
|
describe('processMetadata', () => {
|
||||||
const siteDir = path.join(__dirname, '__fixtures__', 'website');
|
const fixtureDir = path.join(__dirname, '__fixtures__');
|
||||||
|
const simpleSiteDir = path.join(fixtureDir, 'simple-site');
|
||||||
const siteConfig = {
|
const siteConfig = {
|
||||||
title: 'Hello',
|
title: 'Hello',
|
||||||
baseUrl: '/',
|
baseUrl: '/',
|
||||||
url: 'https://docusaurus.io',
|
url: 'https://docusaurus.io',
|
||||||
};
|
};
|
||||||
const pluginPath = 'docs';
|
const pluginPath = 'docs';
|
||||||
const docsDir = path.resolve(siteDir, pluginPath);
|
const docsDir = path.resolve(simpleSiteDir, pluginPath);
|
||||||
|
|
||||||
test('normal docs', async () => {
|
test('normal docs', async () => {
|
||||||
const sourceA = path.join('foo', 'bar.md');
|
const sourceA = path.join('foo', 'bar.md');
|
||||||
|
@ -29,7 +30,7 @@ describe('processMetadata', () => {
|
||||||
order: {},
|
order: {},
|
||||||
siteConfig,
|
siteConfig,
|
||||||
docsBasePath: pluginPath,
|
docsBasePath: pluginPath,
|
||||||
siteDir,
|
siteDir: simpleSiteDir,
|
||||||
}),
|
}),
|
||||||
processMetadata({
|
processMetadata({
|
||||||
source: sourceB,
|
source: sourceB,
|
||||||
|
@ -37,7 +38,7 @@ describe('processMetadata', () => {
|
||||||
order: {},
|
order: {},
|
||||||
siteConfig,
|
siteConfig,
|
||||||
docsBasePath: pluginPath,
|
docsBasePath: pluginPath,
|
||||||
siteDir,
|
siteDir: simpleSiteDir,
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -65,7 +66,7 @@ describe('processMetadata', () => {
|
||||||
order: {},
|
order: {},
|
||||||
siteConfig,
|
siteConfig,
|
||||||
docsBasePath: pluginPath,
|
docsBasePath: pluginPath,
|
||||||
siteDir,
|
siteDir: simpleSiteDir,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(data).toEqual({
|
expect(data).toEqual({
|
||||||
|
@ -87,7 +88,7 @@ describe('processMetadata', () => {
|
||||||
order: {},
|
order: {},
|
||||||
siteConfig,
|
siteConfig,
|
||||||
docsBasePath: pluginPath,
|
docsBasePath: pluginPath,
|
||||||
siteDir,
|
siteDir: simpleSiteDir,
|
||||||
editUrl,
|
editUrl,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -110,7 +111,7 @@ describe('processMetadata', () => {
|
||||||
order: {},
|
order: {},
|
||||||
siteConfig,
|
siteConfig,
|
||||||
docsBasePath: pluginPath,
|
docsBasePath: pluginPath,
|
||||||
siteDir,
|
siteDir: simpleSiteDir,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(data).toEqual({
|
expect(data).toEqual({
|
||||||
|
@ -122,4 +123,46 @@ describe('processMetadata', () => {
|
||||||
description: 'Lorem ipsum.',
|
description: 'Lorem ipsum.',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('docs with last update time and author', async () => {
|
||||||
|
const source = 'lorem.md';
|
||||||
|
const data = await processMetadata({
|
||||||
|
source,
|
||||||
|
docsDir,
|
||||||
|
order: {},
|
||||||
|
siteConfig,
|
||||||
|
docsBasePath: pluginPath,
|
||||||
|
siteDir: simpleSiteDir,
|
||||||
|
showLastUpdateAuthor: true,
|
||||||
|
showLastUpdateTime: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(data).toEqual({
|
||||||
|
id: 'lorem',
|
||||||
|
permalink: '/docs/lorem',
|
||||||
|
source: path.join('@site', pluginPath, source),
|
||||||
|
title: 'lorem',
|
||||||
|
editUrl: 'https://github.com/customUrl/docs/lorem.md',
|
||||||
|
description: 'Lorem ipsum.',
|
||||||
|
lastUpdatedAt: '1539502055',
|
||||||
|
lastUpdatedBy: 'Author',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('docs with invalid id', async () => {
|
||||||
|
const badSiteDir = path.join(fixtureDir, 'bad-site');
|
||||||
|
|
||||||
|
return processMetadata({
|
||||||
|
source: 'invalid-id.md',
|
||||||
|
docsDir: path.join(badSiteDir, 'docs'),
|
||||||
|
order: {},
|
||||||
|
siteConfig,
|
||||||
|
docsBasePath: 'docs',
|
||||||
|
siteDir: simpleSiteDir,
|
||||||
|
}).catch(e =>
|
||||||
|
expect(e).toMatchInlineSnapshot(
|
||||||
|
`[Error: Document id cannot include "/".]`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -218,6 +218,29 @@ describe('createOrder', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('multiple sidebars with unknown sidebar item type', () => {
|
||||||
|
expect(() =>
|
||||||
|
createOrder({
|
||||||
|
docs: [
|
||||||
|
{
|
||||||
|
type: 'category',
|
||||||
|
label: 'Category1',
|
||||||
|
items: [{type: 'endi', id: 'doc1'}, {type: 'doc', id: 'doc2'}],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
otherDocs: [
|
||||||
|
{
|
||||||
|
type: 'category',
|
||||||
|
label: 'Category1',
|
||||||
|
items: [{type: 'doc', id: 'doc5'}],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
).toThrowErrorMatchingInlineSnapshot(
|
||||||
|
`"Unknown item type: endi. Item: {\\"type\\":\\"endi\\",\\"id\\":\\"doc1\\"}"`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
test('edge cases', () => {
|
test('edge cases', () => {
|
||||||
expect(createOrder({})).toEqual({});
|
expect(createOrder({})).toEqual({});
|
||||||
expect(createOrder(undefined)).toEqual({});
|
expect(createOrder(undefined)).toEqual({});
|
||||||
|
|
|
@ -11,40 +11,43 @@ import loadSidebars from '../sidebars';
|
||||||
/* eslint-disable global-require, import/no-dynamic-require */
|
/* eslint-disable global-require, import/no-dynamic-require */
|
||||||
|
|
||||||
describe('loadSidebars', () => {
|
describe('loadSidebars', () => {
|
||||||
|
const fixtureDir = path.join(__dirname, '__fixtures__', 'sidebars');
|
||||||
test('sidebars with known sidebar item type', async () => {
|
test('sidebars with known sidebar item type', async () => {
|
||||||
const sidebarPath = path.join(
|
const sidebarPath = path.join(fixtureDir, 'sidebars.json');
|
||||||
__dirname,
|
|
||||||
'__fixtures__',
|
|
||||||
'website',
|
|
||||||
'sidebars.json',
|
|
||||||
);
|
|
||||||
const result = loadSidebars(sidebarPath);
|
const result = loadSidebars(sidebarPath);
|
||||||
expect(result).toMatchSnapshot();
|
expect(result).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('sidebars with deep level of category', async () => {
|
test('sidebars with deep level of category', async () => {
|
||||||
const sidebarPath = path.join(
|
const sidebarPath = path.join(fixtureDir, 'sidebars-category.js');
|
||||||
__dirname,
|
|
||||||
'__fixtures__',
|
|
||||||
'website',
|
|
||||||
'sidebars-category.js',
|
|
||||||
);
|
|
||||||
const result = loadSidebars(sidebarPath);
|
const result = loadSidebars(sidebarPath);
|
||||||
expect(result).toMatchSnapshot();
|
expect(result).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('sidebars with unknown sidebar item type', async () => {
|
test('sidebars with category but category.items is not an array', async () => {
|
||||||
const sidebarPath = path.join(
|
const sidebarPath = path.join(
|
||||||
__dirname,
|
fixtureDir,
|
||||||
'__fixtures__',
|
'sidebars-category-wrong-items.json',
|
||||||
'website',
|
|
||||||
'bad-sidebars.json',
|
|
||||||
);
|
);
|
||||||
|
expect(() => loadSidebars(sidebarPath)).toThrowErrorMatchingInlineSnapshot(
|
||||||
|
`"Error loading \\"Category Label\\" category. Category items must be array."`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sidebars with unknown sidebar item type', async () => {
|
||||||
|
const sidebarPath = path.join(fixtureDir, 'sidebars-unknown-type.json');
|
||||||
expect(() => loadSidebars(sidebarPath)).toThrowErrorMatchingInlineSnapshot(
|
expect(() => loadSidebars(sidebarPath)).toThrowErrorMatchingInlineSnapshot(
|
||||||
`"Unknown sidebar item type: superman"`,
|
`"Unknown sidebar item type: superman"`,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('sidebars with known sidebar item type but wrong field', async () => {
|
||||||
|
const sidebarPath = path.join(fixtureDir, 'sidebars-wrong-field.json');
|
||||||
|
expect(() => loadSidebars(sidebarPath)).toThrowErrorMatchingInlineSnapshot(
|
||||||
|
`"Unknown sidebar item keys: href. Item: {\\"type\\":\\"category\\",\\"label\\":\\"category\\",\\"href\\":\\"https://github.com\\"}"`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
test('no sidebars', () => {
|
test('no sidebars', () => {
|
||||||
const result = loadSidebars(null);
|
const result = loadSidebars(null);
|
||||||
expect(result).toEqual({});
|
expect(result).toEqual({});
|
||||||
|
|
|
@ -177,9 +177,8 @@ export default function pluginContentDocs(
|
||||||
case 'doc':
|
case 'doc':
|
||||||
return convertDocLink(item as SidebarItemDoc);
|
return convertDocLink(item as SidebarItemDoc);
|
||||||
case 'link':
|
case 'link':
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unknown sidebar item type: ${item.type}`);
|
break;
|
||||||
}
|
}
|
||||||
return item as SidebarItemLink;
|
return item as SidebarItemLink;
|
||||||
});
|
});
|
||||||
|
@ -208,7 +207,7 @@ export default function pluginContentDocs(
|
||||||
},
|
},
|
||||||
|
|
||||||
async contentLoaded({content, actions}) {
|
async contentLoaded({content, actions}) {
|
||||||
if (!content) {
|
if (!content || Object.keys(content.docsMetadata).length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ export default function getFileLastUpdate(
|
||||||
if (!shell.which('git')) {
|
if (!shell.which('git')) {
|
||||||
if (!showedGitRequirementError) {
|
if (!showedGitRequirementError) {
|
||||||
showedGitRequirementError = true;
|
showedGitRequirementError = true;
|
||||||
console.log('Sorry, the docs plugin last update options require Git.');
|
console.warn('Sorry, the docs plugin last update options require Git.');
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -44,7 +44,7 @@ function normalizeCategory(
|
||||||
|
|
||||||
if (!Array.isArray(category.items)) {
|
if (!Array.isArray(category.items)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Error loading ${category.label} category. Category items must be array.`,
|
`Error loading "${category.label}" category. Category items must be array.`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,15 +62,11 @@ function normalizeCategory(
|
||||||
assertItem(item, ['href', 'label']);
|
assertItem(item, ['href', 'label']);
|
||||||
break;
|
break;
|
||||||
case 'ref':
|
case 'ref':
|
||||||
|
case 'doc':
|
||||||
assertItem(item, ['id']);
|
assertItem(item, ['id']);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (item.type !== 'doc') {
|
throw new Error(`Unknown sidebar item type: ${item.type}`);
|
||||||
throw new Error(`Unknown sidebar item type: ${item.type}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
assertItem(item, ['id']);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return item as SidebarItem;
|
return item as SidebarItem;
|
||||||
|
|
Loading…
Add table
Reference in a new issue