From e610a4ac002e561b8adee5558b178168a2e26742 Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Tue, 5 Apr 2022 14:09:19 +0800 Subject: [PATCH] test: improve test coverage (#7113) --- jest.config.mjs | 1 + .../__snapshots__/codeBlockUtils.test.ts.snap | 87 +++++++++++++++---- .../utils/__tests__/codeBlockUtils.test.ts | 59 ++++++++++++- .../src/utils/codeBlockUtils.ts | 40 ++++----- .../src/__tests__/emitUtils.test.ts | 18 +++- packages/docusaurus-utils/src/emitUtils.ts | 12 ++- .../{configs => config}/configAsync.config.js | 0 .../createConfig.config.js | 0 .../createConfigAsync.config.js | 0 .../incomplete.config.js} | 0 .../wrong.config.js} | 0 .../simple-site/docusaurus.config.js | 3 + .../simple-site/i18n/en/code.json | 6 ++ .../__snapshots__/config.test.ts.snap | 10 ++- .../__snapshots__/siteMetadata.test.ts.snap | 15 ++++ .../src/server/__tests__/config.test.ts | 13 +-- .../src/server/__tests__/siteMetadata.test.ts | 32 ++++++- 17 files changed, 235 insertions(+), 61 deletions(-) rename packages/docusaurus/src/server/__tests__/__fixtures__/{configs => config}/configAsync.config.js (100%) rename packages/docusaurus/src/server/__tests__/__fixtures__/{configs => config}/createConfig.config.js (100%) rename packages/docusaurus/src/server/__tests__/__fixtures__/{configs => config}/createConfigAsync.config.js (100%) rename packages/docusaurus/src/server/__tests__/__fixtures__/{bad-site/docusaurus.config.js => config/incomplete.config.js} (100%) rename packages/docusaurus/src/server/__tests__/__fixtures__/{wrong-site/docusaurus.config.js => config/wrong.config.js} (100%) create mode 100644 packages/docusaurus/src/server/__tests__/__fixtures__/simple-site/i18n/en/code.json create mode 100644 packages/docusaurus/src/server/__tests__/__snapshots__/siteMetadata.test.ts.snap diff --git a/jest.config.mjs b/jest.config.mjs index 7163875c41..479ebd5948 100644 --- a/jest.config.mjs +++ b/jest.config.mjs @@ -25,6 +25,7 @@ const ignorePatterns = [ '/packages/docusaurus-theme-classic/lib-next', '/packages/docusaurus-theme-common/lib', '/packages/docusaurus-migrate/lib', + '/jest', ]; export default { diff --git a/packages/docusaurus-theme-common/src/utils/__tests__/__snapshots__/codeBlockUtils.test.ts.snap b/packages/docusaurus-theme-common/src/utils/__tests__/__snapshots__/codeBlockUtils.test.ts.snap index 97a8976893..bca094fc9e 100644 --- a/packages/docusaurus-theme-common/src/utils/__tests__/__snapshots__/codeBlockUtils.test.ts.snap +++ b/packages/docusaurus-theme-common/src/utils/__tests__/__snapshots__/codeBlockUtils.test.ts.snap @@ -74,7 +74,20 @@ bbbbb", } `; -exports[`parseLines respects language 1`] = ` +exports[`parseLines respects language: html 1`] = ` +{ + "code": "aaaa +{/* highlight-next-line */} +bbbbb +dddd", + "highlightLines": [ + 0, + 3, + ], +} +`; + +exports[`parseLines respects language: js 1`] = ` { "code": "# highlight-next-line aaaaa @@ -83,31 +96,47 @@ bbbbb", } `; -exports[`parseLines respects language 2`] = ` +exports[`parseLines respects language: jsx 1`] = ` { - "code": "/* highlight-next-line */ -aaaaa -bbbbb", - "highlightLines": [], -} -`; - -exports[`parseLines respects language 3`] = ` -{ - "code": "// highlight-next-line -aaaa -/* highlight-next-line */ + "code": "aaaa bbbbb -ccccc dddd", "highlightLines": [ - 4, + 0, + 1, ], } `; -exports[`parseLines respects language 4`] = ` +exports[`parseLines respects language: md 1`] = ` +{ + "code": "--- +aaa: boo +--- + +aaaa + +
+foo +
+ +bbbbb +dddd + +\`\`\`js +// highlight-next-line +console.log(\\"preserved\\"); +\`\`\`", + "highlightLines": [ + 1, + 7, + 11, + ], +} +`; + +exports[`parseLines respects language: none 1`] = ` { "code": "aaaa bbbbb @@ -121,3 +150,27 @@ dddd", ], } `; + +exports[`parseLines respects language: py 1`] = ` +{ + "code": "/* highlight-next-line */ +aaaaa +bbbbb", + "highlightLines": [], +} +`; + +exports[`parseLines respects language: py 2`] = ` +{ + "code": "// highlight-next-line +aaaa +/* highlight-next-line */ +bbbbb +ccccc + +dddd", + "highlightLines": [ + 4, + ], +} +`; diff --git a/packages/docusaurus-theme-common/src/utils/__tests__/codeBlockUtils.test.ts b/packages/docusaurus-theme-common/src/utils/__tests__/codeBlockUtils.test.ts index bc4e77b0d1..f2ddc02bb6 100644 --- a/packages/docusaurus-theme-common/src/utils/__tests__/codeBlockUtils.test.ts +++ b/packages/docusaurus-theme-common/src/utils/__tests__/codeBlockUtils.test.ts @@ -140,7 +140,7 @@ bbbbb`, '', 'js', ), - ).toMatchSnapshot(); + ).toMatchSnapshot('js'); expect( parseLines( `/* highlight-next-line */ @@ -149,7 +149,7 @@ bbbbb`, '', 'py', ), - ).toMatchSnapshot(); + ).toMatchSnapshot('py'); expect( parseLines( `// highlight-next-line @@ -163,7 +163,7 @@ dddd`, '', 'py', ), - ).toMatchSnapshot(); + ).toMatchSnapshot('py'); expect( parseLines( `// highlight-next-line @@ -177,6 +177,57 @@ dddd`, '', '', ), - ).toMatchSnapshot(); + ).toMatchSnapshot('none'); + expect( + parseLines( + `// highlight-next-line +aaaa +{/* highlight-next-line */} +bbbbb + +dddd`, + '', + 'jsx', + ), + ).toMatchSnapshot('jsx'); + expect( + parseLines( + `// highlight-next-line +aaaa +{/* highlight-next-line */} +bbbbb + +dddd`, + '', + 'html', + ), + ).toMatchSnapshot('html'); + expect( + parseLines( + `--- +# highlight-next-line +aaa: boo +--- + +aaaa + +
+{/* highlight-next-line */} +foo +
+ +bbbbb + +dddd + +\`\`\`js +// highlight-next-line +console.log("preserved"); +\`\`\` +`, + '', + 'md', + ), + ).toMatchSnapshot('md'); }); }); diff --git a/packages/docusaurus-theme-common/src/utils/codeBlockUtils.ts b/packages/docusaurus-theme-common/src/utils/codeBlockUtils.ts index cc28c5d21f..46277defbf 100644 --- a/packages/docusaurus-theme-common/src/utils/codeBlockUtils.ts +++ b/packages/docusaurus-theme-common/src/utils/codeBlockUtils.ts @@ -141,29 +141,29 @@ export function parseLines( for (let lineNumber = 0; lineNumber < lines.length; ) { const line = lines[lineNumber]!; const match = line.match(directiveRegex); - if (match !== null) { - const directive = match.slice(1).find((item) => item !== undefined); - switch (directive) { - case 'highlight-next-line': - highlightRange += `${lineNumber},`; - break; - - case 'highlight-start': - highlightBlockStart = lineNumber; - break; - - case 'highlight-end': - highlightRange += `${highlightBlockStart!}-${lineNumber - 1},`; - break; - - default: - break; - } - lines.splice(lineNumber, 1); - } else { + if (!match) { // lines without directives are unchanged lineNumber += 1; + continue; } + const directive = match.slice(1).find((item) => item !== undefined); + switch (directive) { + case 'highlight-next-line': + highlightRange += `${lineNumber},`; + break; + + case 'highlight-start': + highlightBlockStart = lineNumber; + break; + + case 'highlight-end': + highlightRange += `${highlightBlockStart!}-${lineNumber - 1},`; + break; + + default: + break; + } + lines.splice(lineNumber, 1); } const highlightLines = rangeParser(highlightRange); code = lines.join('\n'); diff --git a/packages/docusaurus-utils/src/__tests__/emitUtils.test.ts b/packages/docusaurus-utils/src/__tests__/emitUtils.test.ts index e5f975abb9..236d9c224d 100644 --- a/packages/docusaurus-utils/src/__tests__/emitUtils.test.ts +++ b/packages/docusaurus-utils/src/__tests__/emitUtils.test.ts @@ -11,7 +11,7 @@ import path from 'path'; import fs from 'fs-extra'; describe('readOutputHTMLFile', () => { - it('trailing slash undefined', async () => { + it('reads both files with trailing slash undefined', async () => { await expect( readOutputHTMLFile( '/file', @@ -41,7 +41,7 @@ describe('readOutputHTMLFile', () => { ).then(String), ).resolves.toBe('folder\n'); }); - it('trailing slash true', async () => { + it('reads only folder with trailing slash true', async () => { await expect( readOutputHTMLFile( '/folder', @@ -57,7 +57,7 @@ describe('readOutputHTMLFile', () => { ).then(String), ).resolves.toBe('folder\n'); }); - it('trailing slash false', async () => { + it('reads only file trailing slash false', async () => { await expect( readOutputHTMLFile( '/file', @@ -73,6 +73,18 @@ describe('readOutputHTMLFile', () => { ).then(String), ).resolves.toBe('file\n'); }); + // Can it ever happen? + it('throws if file does not exist', async () => { + await expect( + readOutputHTMLFile( + '/nonExistent', + path.join(__dirname, '__fixtures__/build-snap'), + undefined, + ).then(String), + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Expected output HTML file to be found at /packages/docusaurus-utils/src/__tests__/__fixtures__/build-snap/nonExistent/index.html."`, + ); + }); }); describe('generate', () => { diff --git a/packages/docusaurus-utils/src/emitUtils.ts b/packages/docusaurus-utils/src/emitUtils.ts index 89680f92ad..b0c9a3ab27 100644 --- a/packages/docusaurus-utils/src/emitUtils.ts +++ b/packages/docusaurus-utils/src/emitUtils.ts @@ -83,18 +83,16 @@ export async function readOutputHTMLFile( outDir, `${permalink.replace(/\/$/, '')}.html`, ); - if (trailingSlash) { - return fs.readFile(withTrailingSlashPath); - } else if (trailingSlash === false) { - return fs.readFile(withoutTrailingSlashPath); - } const HTMLPath = await findAsyncSequential( - [withTrailingSlashPath, withoutTrailingSlashPath], + [ + trailingSlash !== false && withTrailingSlashPath, + trailingSlash !== true && withoutTrailingSlashPath, + ].filter((p): p is string => Boolean(p)), fs.pathExists, ); if (!HTMLPath) { throw new Error( - `Expected output HTML file to be found at ${withTrailingSlashPath}`, + `Expected output HTML file to be found at ${withTrailingSlashPath}.`, ); } return fs.readFile(HTMLPath); diff --git a/packages/docusaurus/src/server/__tests__/__fixtures__/configs/configAsync.config.js b/packages/docusaurus/src/server/__tests__/__fixtures__/config/configAsync.config.js similarity index 100% rename from packages/docusaurus/src/server/__tests__/__fixtures__/configs/configAsync.config.js rename to packages/docusaurus/src/server/__tests__/__fixtures__/config/configAsync.config.js diff --git a/packages/docusaurus/src/server/__tests__/__fixtures__/configs/createConfig.config.js b/packages/docusaurus/src/server/__tests__/__fixtures__/config/createConfig.config.js similarity index 100% rename from packages/docusaurus/src/server/__tests__/__fixtures__/configs/createConfig.config.js rename to packages/docusaurus/src/server/__tests__/__fixtures__/config/createConfig.config.js diff --git a/packages/docusaurus/src/server/__tests__/__fixtures__/configs/createConfigAsync.config.js b/packages/docusaurus/src/server/__tests__/__fixtures__/config/createConfigAsync.config.js similarity index 100% rename from packages/docusaurus/src/server/__tests__/__fixtures__/configs/createConfigAsync.config.js rename to packages/docusaurus/src/server/__tests__/__fixtures__/config/createConfigAsync.config.js diff --git a/packages/docusaurus/src/server/__tests__/__fixtures__/bad-site/docusaurus.config.js b/packages/docusaurus/src/server/__tests__/__fixtures__/config/incomplete.config.js similarity index 100% rename from packages/docusaurus/src/server/__tests__/__fixtures__/bad-site/docusaurus.config.js rename to packages/docusaurus/src/server/__tests__/__fixtures__/config/incomplete.config.js diff --git a/packages/docusaurus/src/server/__tests__/__fixtures__/wrong-site/docusaurus.config.js b/packages/docusaurus/src/server/__tests__/__fixtures__/config/wrong.config.js similarity index 100% rename from packages/docusaurus/src/server/__tests__/__fixtures__/wrong-site/docusaurus.config.js rename to packages/docusaurus/src/server/__tests__/__fixtures__/config/wrong.config.js diff --git a/packages/docusaurus/src/server/__tests__/__fixtures__/simple-site/docusaurus.config.js b/packages/docusaurus/src/server/__tests__/__fixtures__/simple-site/docusaurus.config.js index 994e27fa63..a67a70d528 100644 --- a/packages/docusaurus/src/server/__tests__/__fixtures__/simple-site/docusaurus.config.js +++ b/packages/docusaurus/src/server/__tests__/__fixtures__/simple-site/docusaurus.config.js @@ -22,4 +22,7 @@ module.exports = { ], '@docusaurus/plugin-content-pages', ], + clientModules: [ + 'foo.js' + ] }; diff --git a/packages/docusaurus/src/server/__tests__/__fixtures__/simple-site/i18n/en/code.json b/packages/docusaurus/src/server/__tests__/__fixtures__/simple-site/i18n/en/code.json new file mode 100644 index 0000000000..768c5072a6 --- /dev/null +++ b/packages/docusaurus/src/server/__tests__/__fixtures__/simple-site/i18n/en/code.json @@ -0,0 +1,6 @@ +{ + "foo": { + "message": "bar", + "description": "foo for bar" + } +} diff --git a/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap b/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap index 914b41fe1c..abaaab349c 100644 --- a/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap +++ b/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap @@ -34,7 +34,7 @@ exports[`loadSiteConfig website with valid async config 1`] = ` "titleDelimiter": "|", "url": "https://docusaurus.io", }, - "siteConfigPath": "/packages/docusaurus/src/server/__tests__/__fixtures__/configs/configAsync.config.js", + "siteConfigPath": "/packages/docusaurus/src/server/__tests__/__fixtures__/config/configAsync.config.js", } `; @@ -72,7 +72,7 @@ exports[`loadSiteConfig website with valid async config creator function 1`] = ` "titleDelimiter": "|", "url": "https://docusaurus.io", }, - "siteConfigPath": "/packages/docusaurus/src/server/__tests__/__fixtures__/configs/createConfigAsync.config.js", + "siteConfigPath": "/packages/docusaurus/src/server/__tests__/__fixtures__/config/createConfigAsync.config.js", } `; @@ -110,7 +110,7 @@ exports[`loadSiteConfig website with valid config creator function 1`] = ` "titleDelimiter": "|", "url": "https://docusaurus.io", }, - "siteConfigPath": "/packages/docusaurus/src/server/__tests__/__fixtures__/configs/createConfig.config.js", + "siteConfigPath": "/packages/docusaurus/src/server/__tests__/__fixtures__/config/createConfig.config.js", } `; @@ -119,7 +119,9 @@ exports[`loadSiteConfig website with valid siteConfig 1`] = ` "siteConfig": { "baseUrl": "/", "baseUrlIssueBanner": true, - "clientModules": [], + "clientModules": [ + "foo.js", + ], "customFields": {}, "favicon": "img/docusaurus.ico", "i18n": { diff --git a/packages/docusaurus/src/server/__tests__/__snapshots__/siteMetadata.test.ts.snap b/packages/docusaurus/src/server/__tests__/__snapshots__/siteMetadata.test.ts.snap new file mode 100644 index 0000000000..667dc1216a --- /dev/null +++ b/packages/docusaurus/src/server/__tests__/__snapshots__/siteMetadata.test.ts.snap @@ -0,0 +1,15 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`loadSiteMetadata warns about plugin version mismatch 1`] = ` +{ + "docusaurusVersion": "", + "pluginVersions": { + "docusaurus-plugin-content-docs": { + "name": "@docusaurus/plugin-content-docs", + "type": "package", + "version": "1.0.0", + }, + }, + "siteVersion": "random-version", +} +`; diff --git a/packages/docusaurus/src/server/__tests__/config.test.ts b/packages/docusaurus/src/server/__tests__/config.test.ts index 7c3fb39b80..12b4be6415 100644 --- a/packages/docusaurus/src/server/__tests__/config.test.ts +++ b/packages/docusaurus/src/server/__tests__/config.test.ts @@ -9,7 +9,7 @@ import path from 'path'; import {loadSiteConfig} from '../config'; describe('loadSiteConfig', () => { - const siteDir = path.join(__dirname, '__fixtures__', 'configs'); + const siteDir = path.join(__dirname, '__fixtures__', 'config'); it('website with valid siteConfig', async () => { const config = await loadSiteConfig({ @@ -49,7 +49,8 @@ describe('loadSiteConfig', () => { it('website with incomplete siteConfig', async () => { await expect( loadSiteConfig({ - siteDir: path.join(__dirname, '__fixtures__', 'bad-site'), + siteDir, + customConfigFilePath: 'incomplete.config.js', }), ).rejects.toThrowErrorMatchingInlineSnapshot(` "\\"url\\" is required @@ -60,7 +61,8 @@ describe('loadSiteConfig', () => { it('website with useless field (wrong field) in siteConfig', async () => { await expect( loadSiteConfig({ - siteDir: path.join(__dirname, '__fixtures__', 'wrong-site'), + siteDir, + customConfigFilePath: 'wrong.config.js', }), ).rejects.toThrowErrorMatchingInlineSnapshot(` "These field(s) (\\"useLessField\\",) are not recognized in docusaurus.config.js. @@ -72,10 +74,11 @@ describe('loadSiteConfig', () => { it('website with no siteConfig', async () => { await expect( loadSiteConfig({ - siteDir: path.join(__dirname, '__fixtures__', 'nonExisting'), + siteDir, + customConfigFilePath: 'nonExistent.config.js', }), ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Config file at \\"/packages/docusaurus/src/server/__tests__/__fixtures__/nonExisting/docusaurus.config.js\\" not found."`, + `"Config file at \\"/packages/docusaurus/src/server/__tests__/__fixtures__/config/nonExistent.config.js\\" not found."`, ); }); }); diff --git a/packages/docusaurus/src/server/__tests__/siteMetadata.test.ts b/packages/docusaurus/src/server/__tests__/siteMetadata.test.ts index b12e0a7e17..12c62dcd54 100644 --- a/packages/docusaurus/src/server/__tests__/siteMetadata.test.ts +++ b/packages/docusaurus/src/server/__tests__/siteMetadata.test.ts @@ -5,7 +5,8 @@ * LICENSE file in the root directory of this source tree. */ -import {getPluginVersion} from '../siteMetadata'; +import {jest} from '@jest/globals'; +import {getPluginVersion, loadSiteMetadata} from '../siteMetadata'; import path from 'path'; describe('getPluginVersion', () => { @@ -33,3 +34,32 @@ describe('getPluginVersion', () => { await expect(getPluginVersion('/', '/')).resolves.toEqual({type: 'local'}); }); }); + +describe('loadSiteMetadata', () => { + it('warns about plugin version mismatch', async () => { + const consoleMock = jest + .spyOn(console, 'error') + .mockImplementation(() => {}); + await expect( + loadSiteMetadata({ + plugins: [ + { + name: 'docusaurus-plugin-content-docs', + version: { + type: 'package', + version: '1.0.0', + name: '@docusaurus/plugin-content-docs', + }, + }, + ], + siteDir: path.join(__dirname, '__fixtures__/siteMetadata'), + }), + ).resolves.toMatchSnapshot(); + // cSpell:ignore mdocusaurus + expect(consoleMock.mock.calls[0][0]).toMatchInlineSnapshot(` + "[ERROR] Invalid docusaurus-plugin-content-docs version 1.0.0. + All official @docusaurus/* packages should have the exact same version as @docusaurus/core (). + Maybe you want to check, or regenerate your yarn.lock or package-lock.json file?" + `); + }); +});