mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-10 07:37:19 +02:00
test: strengthen internal types (#7488)
This commit is contained in:
parent
d50fe3b670
commit
cd21a31005
15 changed files with 67 additions and 55 deletions
13
jest/deps.d.ts
vendored
13
jest/deps.d.ts
vendored
|
@ -7,9 +7,18 @@
|
|||
|
||||
// modules only used in tests
|
||||
|
||||
declare module 'to-vfile';
|
||||
declare module 'to-vfile' {
|
||||
import type {VFile} from 'vfile';
|
||||
|
||||
declare module 'remark-mdx';
|
||||
export function read(path: string, encoding?: string): Promise<VFile>;
|
||||
}
|
||||
|
||||
declare module 'remark-mdx' {
|
||||
import type {Plugin} from 'unified';
|
||||
|
||||
const mdx: Plugin;
|
||||
export = mdx;
|
||||
}
|
||||
|
||||
declare module '@testing-utils/git' {
|
||||
const createTempRepo: typeof import('./utils/git').createTempRepo;
|
||||
|
|
|
@ -10,8 +10,8 @@ import vfile from 'to-vfile';
|
|||
import postcss from 'postcss';
|
||||
import postCssRemoveOverriddenCustomProperties from '../index';
|
||||
|
||||
const processFixture = (name: string) => {
|
||||
const input = vfile.readSync(
|
||||
const processFixture = async (name: string) => {
|
||||
const input = await vfile.read(
|
||||
path.join(__dirname, '__fixtures__', `${name}.css`),
|
||||
'utf8',
|
||||
);
|
||||
|
@ -23,11 +23,11 @@ const processFixture = (name: string) => {
|
|||
};
|
||||
|
||||
describe('remove-overridden-custom-properties', () => {
|
||||
it('overridden custom properties should be removed', () => {
|
||||
expect(processFixture('normal')).toMatchSnapshot();
|
||||
it('overridden custom properties should be removed', async () => {
|
||||
await expect(processFixture('normal')).resolves.toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('overridden custom properties with `!important` rule should not be removed', () => {
|
||||
expect(processFixture('important_rule')).toMatchSnapshot();
|
||||
it('overridden custom properties with `!important` rule should not be removed', async () => {
|
||||
await expect(processFixture('important_rule')).resolves.toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -552,7 +552,7 @@ async function migrateVersionedSidebar(
|
|||
(topLevel: SidebarEntries, value) => {
|
||||
const key = value[0].replace(versionRegex, '');
|
||||
topLevel[key] = Object.entries(value[1]).reduce<{
|
||||
[key: string]: Array<string | {[key: string]: unknown}>;
|
||||
[key: string]: (string | {[key: string]: unknown})[];
|
||||
}>((acc, val) => {
|
||||
acc[val[0].replace(versionRegex, '')] = (
|
||||
val[1] as SidebarEntry[]
|
||||
|
|
|
@ -34,7 +34,7 @@ export type SidebarEntry =
|
|||
export type SidebarEntries = {
|
||||
[key: string]:
|
||||
| {[key: string]: unknown}
|
||||
| Array<{[key: string]: unknown} | string>;
|
||||
| ({[key: string]: unknown} | string)[];
|
||||
};
|
||||
|
||||
export type VersionTwoConfig = {
|
||||
|
@ -49,7 +49,7 @@ export type VersionTwoConfig = {
|
|||
githubHost?: string;
|
||||
onBrokenLinks: string;
|
||||
onBrokenMarkdownLinks: string;
|
||||
plugins: Array<[string, {[key: string]: unknown}]>;
|
||||
plugins: [string, {[key: string]: unknown}][];
|
||||
themes?: [];
|
||||
presets: [[string, ClassicPresetEntries]];
|
||||
themeConfig: {
|
||||
|
@ -58,17 +58,14 @@ export type VersionTwoConfig = {
|
|||
logo?: {
|
||||
src?: string;
|
||||
};
|
||||
items: Array<{[key: string]: unknown} | null>;
|
||||
items: ({[key: string]: unknown} | null)[];
|
||||
};
|
||||
image?: string;
|
||||
footer: {
|
||||
links: Array<{
|
||||
links: {
|
||||
title: string;
|
||||
items: Array<{
|
||||
label: string;
|
||||
to: string;
|
||||
}>;
|
||||
}>;
|
||||
items: {label: string; to: string}[];
|
||||
}[];
|
||||
copyright?: string;
|
||||
logo: {
|
||||
src?: string;
|
||||
|
@ -104,26 +101,26 @@ export type VersionOneConfig = {
|
|||
organizationName?: string;
|
||||
projectName?: string;
|
||||
noIndex?: boolean;
|
||||
headerLinks?: Array<{doc: string; href: string; label: string; page: string}>;
|
||||
headerLinks?: {doc: string; href: string; label: string; page: string}[];
|
||||
headerIcon?: string;
|
||||
favicon?: string;
|
||||
colors?: {primaryColor: string};
|
||||
copyright?: string;
|
||||
editUrl?: string;
|
||||
customDocsPath?: string;
|
||||
users?: Array<{[key: string]: unknown}>;
|
||||
users?: {[key: string]: unknown}[];
|
||||
disableHeaderTitle?: string;
|
||||
disableTitleTagline?: string;
|
||||
separateCss?: Array<{[key: string]: unknown}>;
|
||||
separateCss?: {[key: string]: unknown}[];
|
||||
footerIcon?: string;
|
||||
translationRecruitingLink?: string;
|
||||
algolia?: {[key: string]: unknown};
|
||||
gaTrackingId?: string;
|
||||
gaGtag?: boolean;
|
||||
highlight?: {[key: string]: unknown};
|
||||
markdownPlugins?: Array<() => void>;
|
||||
scripts?: Array<{src: string; [key: string]: unknown} | string>;
|
||||
stylesheets?: Array<{href: string; [key: string]: unknown} | string>;
|
||||
markdownPlugins?: (() => void)[];
|
||||
scripts?: ({src: string; [key: string]: unknown} | string)[];
|
||||
stylesheets?: ({href: string; [key: string]: unknown} | string)[];
|
||||
facebookAppId?: string;
|
||||
facebookComments?: true;
|
||||
facebookPixelId?: string;
|
||||
|
|
|
@ -31,6 +31,7 @@ import type {
|
|||
Options,
|
||||
PluginOptions,
|
||||
PropSidebarItemLink,
|
||||
PropSidebars,
|
||||
} from '@docusaurus/plugin-content-docs';
|
||||
import type {
|
||||
SidebarItemsGeneratorOption,
|
||||
|
@ -82,7 +83,7 @@ const createFakeActions = (contentDir: string) => {
|
|||
|
||||
// Query by prefix, because files have a hash at the end so it's not
|
||||
// convenient to query by full filename
|
||||
const getCreatedDataByPrefix = (prefix: string) => {
|
||||
function getCreatedDataByPrefix(prefix: string) {
|
||||
const entry = Object.entries(dataContainer).find(([key]) =>
|
||||
key.startsWith(prefix),
|
||||
);
|
||||
|
@ -92,8 +93,8 @@ Entries created:
|
|||
- ${Object.keys(dataContainer).join('\n- ')}
|
||||
`);
|
||||
}
|
||||
return JSON.parse(entry[1] as string);
|
||||
};
|
||||
return JSON.parse(entry[1] as string) as PropSidebars;
|
||||
}
|
||||
|
||||
// Extra fns useful for tests!
|
||||
const utils = {
|
||||
|
@ -571,8 +572,8 @@ describe('versioned website (community)', () => {
|
|||
allContent: {},
|
||||
});
|
||||
|
||||
utils.checkVersionMetadataPropCreated(currentVersion!);
|
||||
utils.checkVersionMetadataPropCreated(version100!);
|
||||
utils.checkVersionMetadataPropCreated(currentVersion);
|
||||
utils.checkVersionMetadataPropCreated(version100);
|
||||
|
||||
utils.expectSnapshot();
|
||||
});
|
||||
|
|
|
@ -71,6 +71,6 @@ export class ReactContextError extends Error {
|
|||
this.message = `Hook ${
|
||||
this.stack?.split('\n')[1]?.match(/at (?:\w+\.)?(?<name>\w+)/)?.groups!
|
||||
.name ?? ''
|
||||
} is called outside the <${providerName}>. ${additionalInfo || ''}`;
|
||||
} is called outside the <${providerName}>. ${additionalInfo ?? ''}`;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,7 +120,9 @@ function DocSearch({
|
|||
}
|
||||
|
||||
return Promise.all([
|
||||
import('@docsearch/react/modal'),
|
||||
import('@docsearch/react/modal') as Promise<
|
||||
typeof import('@docsearch/react')
|
||||
>,
|
||||
import('@docsearch/react/style'),
|
||||
import('./styles.css'),
|
||||
]).then(([{DocSearchModal: Modal}]) => {
|
||||
|
|
|
@ -42,7 +42,7 @@ describe('normalizePluginOptions', () => {
|
|||
it('throws for invalid options', () => {
|
||||
const options = {foo: 1};
|
||||
expect(() =>
|
||||
normalizePluginOptions(Joi.object({foo: Joi.string()}), options),
|
||||
normalizePluginOptions(Joi.object<object>({foo: Joi.string()}), options),
|
||||
).toThrowErrorMatchingInlineSnapshot(`""foo" must be a string"`);
|
||||
});
|
||||
|
||||
|
@ -90,7 +90,10 @@ describe('normalizeThemeConfig', () => {
|
|||
it('throws for invalid options', () => {
|
||||
const themeConfig = {foo: 1, bar: 1};
|
||||
expect(() =>
|
||||
normalizeThemeConfig(Joi.object({foo: Joi.string()}), themeConfig),
|
||||
normalizeThemeConfig(
|
||||
Joi.object<object>({foo: Joi.string()}),
|
||||
themeConfig,
|
||||
),
|
||||
).toThrowErrorMatchingInlineSnapshot(`""foo" must be a string"`);
|
||||
});
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ class PendingNavigation extends React.Component<Props, State> {
|
|||
? dispatchLifecycleAction('onRouteUpdate', {
|
||||
previousLocation: null,
|
||||
location: this.props.location,
|
||||
})!
|
||||
})
|
||||
: () => {};
|
||||
this.state = {
|
||||
nextRouteHasLoaded: true,
|
||||
|
@ -60,14 +60,14 @@ class PendingNavigation extends React.Component<Props, State> {
|
|||
this.routeUpdateCleanupCb = dispatchLifecycleAction('onRouteUpdate', {
|
||||
previousLocation: this.previousLocation,
|
||||
location: nextLocation,
|
||||
})!;
|
||||
});
|
||||
|
||||
// Load data while the old screen remains. Force preload instead of using
|
||||
// `window.docusaurus`, because we want to avoid loading screen even when
|
||||
// user is on saveData
|
||||
preload(nextLocation.pathname)
|
||||
.then(() => {
|
||||
this.routeUpdateCleanupCb?.();
|
||||
this.routeUpdateCleanupCb();
|
||||
this.setState({nextRouteHasLoaded: true});
|
||||
})
|
||||
.catch((e: unknown) => console.warn(e));
|
||||
|
|
|
@ -69,7 +69,7 @@ This behavior can have SEO impacts and create relative link issues.
|
|||
|
||||
// The source branch; defaults to the currently checked out branch
|
||||
const sourceBranch =
|
||||
process.env.CURRENT_BRANCH ||
|
||||
process.env.CURRENT_BRANCH ??
|
||||
shell.exec('git rev-parse --abbrev-ref HEAD', {silent: true}).stdout.trim();
|
||||
|
||||
const gitUser = process.env.GIT_USER;
|
||||
|
@ -90,8 +90,8 @@ This behavior can have SEO impacts and create relative link issues.
|
|||
}
|
||||
|
||||
const organizationName =
|
||||
process.env.ORGANIZATION_NAME ||
|
||||
process.env.CIRCLE_PROJECT_USERNAME ||
|
||||
process.env.ORGANIZATION_NAME ??
|
||||
process.env.CIRCLE_PROJECT_USERNAME ??
|
||||
siteConfig.organizationName;
|
||||
if (!organizationName) {
|
||||
throw new Error(
|
||||
|
@ -101,8 +101,8 @@ This behavior can have SEO impacts and create relative link issues.
|
|||
logger.info`organizationName: name=${organizationName}`;
|
||||
|
||||
const projectName =
|
||||
process.env.PROJECT_NAME ||
|
||||
process.env.CIRCLE_PROJECT_REPONAME ||
|
||||
process.env.PROJECT_NAME ??
|
||||
process.env.CIRCLE_PROJECT_REPONAME ??
|
||||
siteConfig.projectName;
|
||||
if (!projectName) {
|
||||
throw new Error(
|
||||
|
@ -113,7 +113,7 @@ This behavior can have SEO impacts and create relative link issues.
|
|||
|
||||
// We never deploy on pull request.
|
||||
const isPullRequest =
|
||||
process.env.CI_PULL_REQUEST || process.env.CIRCLE_PULL_REQUEST;
|
||||
process.env.CI_PULL_REQUEST ?? process.env.CIRCLE_PULL_REQUEST;
|
||||
if (isPullRequest) {
|
||||
shell.echo('Skipping deploy on a pull request.');
|
||||
shell.exit(0);
|
||||
|
@ -136,12 +136,12 @@ You can also set the deploymentBranch property in docusaurus.config.js .`);
|
|||
}
|
||||
|
||||
const deploymentBranch =
|
||||
process.env.DEPLOYMENT_BRANCH || siteConfig.deploymentBranch || 'gh-pages';
|
||||
process.env.DEPLOYMENT_BRANCH ?? siteConfig.deploymentBranch ?? 'gh-pages';
|
||||
logger.info`deploymentBranch: name=${deploymentBranch}`;
|
||||
|
||||
const githubHost =
|
||||
process.env.GITHUB_HOST || siteConfig.githubHost || 'github.com';
|
||||
const githubPort = process.env.GITHUB_PORT || siteConfig.githubPort;
|
||||
process.env.GITHUB_HOST ?? siteConfig.githubHost ?? 'github.com';
|
||||
const githubPort = process.env.GITHUB_PORT ?? siteConfig.githubPort;
|
||||
|
||||
let deploymentRepoURL: string;
|
||||
if (useSSH) {
|
||||
|
@ -214,7 +214,7 @@ You can also set the deploymentBranch property in docusaurus.config.js .`);
|
|||
shellExecLog('git add --all');
|
||||
|
||||
const commitMessage =
|
||||
process.env.CUSTOM_COMMIT_MESSAGE ||
|
||||
process.env.CUSTOM_COMMIT_MESSAGE ??
|
||||
`Deploy website - based on ${currentCommit}`;
|
||||
const commitResults = shellExecLog(`git commit -m "${commitMessage}"`);
|
||||
if (
|
||||
|
|
|
@ -65,7 +65,7 @@ function createExitMock() {
|
|||
});
|
||||
// eslint-disable-next-line jest/require-top-level-describe
|
||||
afterEach(async () => {
|
||||
mock?.mockRestore();
|
||||
mock.mockRestore();
|
||||
});
|
||||
|
||||
return {
|
||||
|
|
|
@ -28,7 +28,7 @@ describe('loadPlugins', () => {
|
|||
name: 'test1',
|
||||
prop: 'a',
|
||||
async loadContent() {
|
||||
// Testing that plugin lifecycle is bound to the plugin instance
|
||||
// Testing that plugin lifecycle is bound to the instance
|
||||
return this.prop;
|
||||
},
|
||||
async contentLoaded({content, actions}) {
|
||||
|
|
|
@ -96,14 +96,14 @@ type SidebarGenerator = (generatorArgs: {
|
|||
/** Useful metadata for the version this sidebar belongs to. */
|
||||
version: {contentPath: string; versionName: string};
|
||||
/** All the docs of that version (unfiltered). */
|
||||
docs: Array<{
|
||||
docs: {
|
||||
id: string;
|
||||
title: string;
|
||||
frontMatter: DocFrontMatter & Record<string, unknown>;
|
||||
source: string;
|
||||
sourceDirName: string;
|
||||
sidebarPosition?: number | undefined;
|
||||
}>;
|
||||
}[];
|
||||
/** Number prefix parser configured for this plugin. */
|
||||
numberPrefixParser: PrefixParser;
|
||||
/** The default category index matcher which you can override. */
|
||||
|
|
|
@ -112,7 +112,7 @@ Turn debug mode on:
|
|||
|
||||
### `offlineModeActivationStrategies` {#offlinemodeactivationstrategies}
|
||||
|
||||
- Type: `Array<'appInstalled' | 'mobile' | 'saveData'| 'queryString' | 'always'>`
|
||||
- Type: `('appInstalled' | 'mobile' | 'saveData'| 'queryString' | 'always')[]`
|
||||
- Default: `['appInstalled', 'queryString', 'standalone']`
|
||||
|
||||
Strategies used to turn the offline mode on:
|
||||
|
@ -194,7 +194,7 @@ The default theme includes an implementation for the reload popup and uses [Infi
|
|||
|
||||
### `pwaHead` {#pwahead}
|
||||
|
||||
- Type: `Array<{ tagName: string } & Record<string,string>>`
|
||||
- Type: `({ tagName: string; [attributeName: string]: string })[]`
|
||||
- Default: `[]`
|
||||
|
||||
Array of objects containing `tagName` and key-value pairs for attributes to inject into the `<head>` tag. Technically you can inject any head tag through this, but it's ideally used for tags to make your site PWA compliant. Here's a list of tag to make your app fully compliant:
|
||||
|
|
|
@ -83,11 +83,11 @@ import TOCInline from '@theme/TOCInline';
|
|||
The `toc` global is just a list of heading items:
|
||||
|
||||
```ts
|
||||
declare const toc: Array<{
|
||||
declare const toc: {
|
||||
value: string;
|
||||
id: string;
|
||||
level: number;
|
||||
}>;
|
||||
}[];
|
||||
```
|
||||
|
||||
Note that the `toc` global is a flat array, so you can easily cut out unwanted nodes or insert extra nodes, and create a new TOC tree.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue