mirror of
https://github.com/facebook/docusaurus.git
synced 2025-06-28 23:48:14 +02:00
refactor: convert Jest infrastructure to TS (#6910)
This commit is contained in:
parent
1305977098
commit
dc975fecbf
4 changed files with 59 additions and 86 deletions
|
@ -35,13 +35,13 @@ export default {
|
||||||
errorOnDeprecated: true,
|
errorOnDeprecated: true,
|
||||||
moduleNameMapper: {
|
moduleNameMapper: {
|
||||||
// Jest can't resolve CSS or asset imports
|
// Jest can't resolve CSS or asset imports
|
||||||
'^.+\\.(css|jpe?g|png|svg)$': '<rootDir>/jest/emptyModule.js',
|
'^.+\\.(css|jpe?g|png|svg|webp)$': '<rootDir>/jest/emptyModule.ts',
|
||||||
|
|
||||||
// Using src instead of lib, so we always get fresh source
|
// Using src instead of lib, so we always get fresh source
|
||||||
'@docusaurus/(browserContext|BrowserOnly|ComponentCreator|constants|docusaurusContext|ExecutionEnvironment|Head|Interpolate|isInternalUrl|Link|Noop|renderRoutes|router|Translate|use.*)':
|
'@docusaurus/(browserContext|BrowserOnly|ComponentCreator|constants|docusaurusContext|ExecutionEnvironment|Head|Interpolate|isInternalUrl|Link|Noop|renderRoutes|router|Translate|use.*)':
|
||||||
'@docusaurus/core/src/client/exports/$1',
|
'@docusaurus/core/src/client/exports/$1',
|
||||||
// Maybe point to a fixture?
|
// Maybe point to a fixture?
|
||||||
'@generated/.*': '<rootDir>/jest/emptyModule.js',
|
'@generated/.*': '<rootDir>/jest/emptyModule.ts',
|
||||||
// TODO use "projects" + multiple configs if we work on another theme?
|
// TODO use "projects" + multiple configs if we work on another theme?
|
||||||
'@theme/(.*)': '@docusaurus/theme-classic/src/theme/$1',
|
'@theme/(.*)': '@docusaurus/theme-classic/src/theme/$1',
|
||||||
'@site/(.*)': 'website/$1',
|
'@site/(.*)': 'website/$1',
|
||||||
|
@ -50,7 +50,7 @@ export default {
|
||||||
'@docusaurus/plugin-content-docs/client':
|
'@docusaurus/plugin-content-docs/client':
|
||||||
'@docusaurus/plugin-content-docs/src/client/index.ts',
|
'@docusaurus/plugin-content-docs/src/client/index.ts',
|
||||||
},
|
},
|
||||||
snapshotSerializers: ['<rootDir>/jest/snapshotPathNormalizer.js'],
|
snapshotSerializers: ['<rootDir>/jest/snapshotPathNormalizer.ts'],
|
||||||
snapshotFormat: {
|
snapshotFormat: {
|
||||||
printBasicPrototype: false,
|
printBasicPrototype: false,
|
||||||
},
|
},
|
||||||
|
|
2
jest/emptyModule.js → jest/emptyModule.ts
vendored
2
jest/emptyModule.js → jest/emptyModule.ts
vendored
|
@ -5,4 +5,4 @@
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module.exports = {};
|
export default {};
|
|
@ -9,82 +9,57 @@
|
||||||
// Forked from https://github.com/tribou/jest-serializer-path/blob/master/lib/index.js
|
// Forked from https://github.com/tribou/jest-serializer-path/blob/master/lib/index.js
|
||||||
// Added some project-specific handlers
|
// Added some project-specific handlers
|
||||||
|
|
||||||
const _ = require('lodash');
|
import _ from 'lodash';
|
||||||
const {escapePath} = require('@docusaurus/utils');
|
import {escapePath} from '@docusaurus/utils';
|
||||||
const {version} = require('@docusaurus/core/package.json');
|
import {version} from '@docusaurus/core/package.json';
|
||||||
const os = require('os');
|
import os from 'os';
|
||||||
const path = require('path');
|
import path from 'path';
|
||||||
const fs = require('fs');
|
import fs from 'fs';
|
||||||
|
|
||||||
module.exports = {
|
export function print(
|
||||||
print(val, serialize) {
|
val: unknown,
|
||||||
let normalizedValue = val;
|
serialize: (val: unknown) => string,
|
||||||
|
): string {
|
||||||
if (_.isError(normalizedValue)) {
|
if (val instanceof Error) {
|
||||||
const message = normalizePaths(normalizedValue.message);
|
const message = normalizePaths(val.message);
|
||||||
const error = new Error(message);
|
const error = new Error(message);
|
||||||
|
const allKeys = [
|
||||||
// Clone hidden props
|
...Object.getOwnPropertyNames(error),
|
||||||
const ownProps = Object.getOwnPropertyNames(error);
|
...Object.keys(val),
|
||||||
// eslint-disable-next-line no-restricted-syntax
|
] as (keyof Error)[];
|
||||||
for (const index in ownProps) {
|
allKeys.forEach((key) => {
|
||||||
if (Object.prototype.hasOwnProperty.call(ownProps, index)) {
|
error[key] = normalizePaths(val[key]) as never;
|
||||||
const key = ownProps[index];
|
});
|
||||||
|
return serialize(error);
|
||||||
error[key] = normalizePaths(normalizedValue[key]);
|
} else if (val && typeof val === 'object') {
|
||||||
}
|
const normalizedValue = _.cloneDeep(val) as Record<string, unknown>;
|
||||||
}
|
|
||||||
|
|
||||||
// Clone normal props
|
|
||||||
// eslint-disable-next-line no-restricted-syntax
|
|
||||||
for (const index in normalizedValue) {
|
|
||||||
if (Object.prototype.hasOwnProperty.call(normalizedValue, index)) {
|
|
||||||
error[index] = normalizePaths(normalizedValue[index]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
normalizedValue = error;
|
|
||||||
} else if (typeof normalizedValue === 'object') {
|
|
||||||
normalizedValue = _.cloneDeep(normalizedValue);
|
|
||||||
|
|
||||||
Object.keys(normalizedValue).forEach((key) => {
|
Object.keys(normalizedValue).forEach((key) => {
|
||||||
normalizedValue[key] = normalizePaths(normalizedValue[key]);
|
normalizedValue[key] = normalizePaths(normalizedValue[key]);
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
normalizedValue = normalizePaths(normalizedValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
return serialize(normalizedValue);
|
return serialize(normalizedValue);
|
||||||
},
|
}
|
||||||
test(val) {
|
return serialize(normalizePaths(val));
|
||||||
let has = false;
|
}
|
||||||
|
|
||||||
if (val && typeof val === 'object') {
|
export function test(val: unknown): boolean {
|
||||||
|
return (
|
||||||
|
(typeof val === 'object' &&
|
||||||
|
val &&
|
||||||
|
Object.keys(val).some((key) =>
|
||||||
|
shouldUpdate((val as Record<string, unknown>)[key]),
|
||||||
|
)) ||
|
||||||
// val.message is non-enumerable in an error
|
// val.message is non-enumerable in an error
|
||||||
if (val.message && shouldUpdate(val.message)) {
|
(val instanceof Error && shouldUpdate(val.message)) ||
|
||||||
has = true;
|
shouldUpdate(val)
|
||||||
}
|
);
|
||||||
|
}
|
||||||
Object.keys(val).forEach((key) => {
|
|
||||||
if (shouldUpdate(val[key])) {
|
|
||||||
has = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if (shouldUpdate(val)) {
|
|
||||||
has = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return has;
|
|
||||||
},
|
|
||||||
normalizePaths,
|
|
||||||
getRealPath,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normalize paths across platforms.
|
* Normalize paths across platforms.
|
||||||
* Filters must be ran on all platforms to guard against false positives
|
* Filters must be ran on all platforms to guard against false positives
|
||||||
*/
|
*/
|
||||||
function normalizePaths(value) {
|
function normalizePaths<T>(value: T): T {
|
||||||
if (typeof value !== 'string') {
|
if (typeof value !== 'string') {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -101,7 +76,7 @@ function normalizePaths(value) {
|
||||||
const homeRealRelativeToTempReal = path.relative(tempDirReal, homeDirReal);
|
const homeRealRelativeToTempReal = path.relative(tempDirReal, homeDirReal);
|
||||||
const homeRealRelativeToTemp = path.relative(tempDir, homeDirReal);
|
const homeRealRelativeToTemp = path.relative(tempDir, homeDirReal);
|
||||||
|
|
||||||
const runner = [
|
const runner: ((val: string) => string)[] = [
|
||||||
// Replace process.cwd with <PROJECT_ROOT>
|
// Replace process.cwd with <PROJECT_ROOT>
|
||||||
(val) => val.split(cwdReal).join('<PROJECT_ROOT>'),
|
(val) => val.split(cwdReal).join('<PROJECT_ROOT>'),
|
||||||
(val) => val.split(cwd).join('<PROJECT_ROOT>'),
|
(val) => val.split(cwd).join('<PROJECT_ROOT>'),
|
||||||
|
@ -149,28 +124,23 @@ function normalizePaths(value) {
|
||||||
(val) => val.replace(/\\(?!")/g, '/'),
|
(val) => val.replace(/\\(?!")/g, '/'),
|
||||||
];
|
];
|
||||||
|
|
||||||
let result = value;
|
let result = value as string;
|
||||||
runner.forEach((current) => {
|
runner.forEach((current) => {
|
||||||
result = current(result);
|
result = current(result);
|
||||||
});
|
});
|
||||||
|
|
||||||
return result;
|
return result as T & string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function shouldUpdate(value) {
|
function shouldUpdate(value: unknown) {
|
||||||
if (typeof value !== 'string') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// return true if value is different from normalized value
|
// return true if value is different from normalized value
|
||||||
return normalizePaths(value) !== value;
|
return typeof value === 'string' && normalizePaths(value) !== value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRealPath(pathname) {
|
function getRealPath(pathname: string) {
|
||||||
try {
|
try {
|
||||||
// eslint-disable-next-line no-restricted-properties
|
// eslint-disable-next-line no-restricted-properties
|
||||||
const realPath = fs.realpathSync(pathname);
|
const realPath = fs.realpathSync(pathname);
|
||||||
|
|
||||||
return realPath;
|
return realPath;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return pathname;
|
return pathname;
|
|
@ -57,7 +57,10 @@ describe('users data', () => {
|
||||||
.message('')
|
.message('')
|
||||||
.required(),
|
.required(),
|
||||||
// The preview should be jest/emptyModule
|
// The preview should be jest/emptyModule
|
||||||
preview: Joi.object({}).unknown(false).required().messages({
|
preview: Joi.object({default: Joi.any()})
|
||||||
|
.unknown(false)
|
||||||
|
.required()
|
||||||
|
.messages({
|
||||||
'object.base':
|
'object.base':
|
||||||
'The image should be hosted on Docusaurus site, and not use remote HTTP or HTTPS URLs. It must be imported with require().',
|
'The image should be hosted on Docusaurus site, and not use remote HTTP or HTTPS URLs. It must be imported with require().',
|
||||||
}),
|
}),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue