improve a bit collectRedirects

This commit is contained in:
slorber 2020-05-25 19:26:36 +02:00
parent d8c163e76b
commit 26beb00476
6 changed files with 180 additions and 22 deletions

View file

@ -0,0 +1,154 @@
/**
* 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.
*/
import {PluginContext, UserPluginOptions} from '../types';
import collectRedirects from '../collectRedirects';
import normalizePluginOptions from '../normalizePluginOptions';
import {removeTrailingSlash} from '../utils';
function createTestPluginContext(
options?: UserPluginOptions,
routesPaths: string[] = [],
): PluginContext {
return {
outDir: '/tmp',
baseUrl: 'https://docusaurus.io',
routesPaths: routesPaths,
options: normalizePluginOptions(options),
};
}
describe('collectRedirects', () => {
test('should collect no redirect for undefined config', () => {
expect(
collectRedirects(createTestPluginContext(undefined, ['/', '/path'])),
).toEqual([]);
});
test('should collect no redirect for empty config', () => {
expect(collectRedirects(createTestPluginContext({}))).toEqual([]);
});
test('should collect redirects to html/exe extension', () => {
expect(
collectRedirects(
createTestPluginContext(
{
fromExtensions: ['html', 'exe'],
},
['/', '/somePath', '/otherPath.html'],
),
),
).toEqual([
{
fromRoutePath: '/somePath.html',
toRoutePath: '/somePath',
},
{
fromRoutePath: '/somePath.exe',
toRoutePath: '/somePath',
},
]);
});
test('should collect redirects to html/exe extension', () => {
expect(
collectRedirects(
createTestPluginContext(
{
toExtensions: ['html', 'exe'],
},
['/', '/somePath', '/otherPath.html'],
),
),
).toEqual([
{
fromRoutePath: '/otherPath',
toRoutePath: '/otherPath.html',
},
]);
});
test('should collect redirects with custom redirect creator', () => {
expect(
collectRedirects(
createTestPluginContext(
{
createRedirects: (routePath) => {
return [
`${removeTrailingSlash(routePath)}/some/path/suffix1`,
`${removeTrailingSlash(routePath)}/some/other/path/suffix2`,
];
},
},
['/', '/testpath', '/otherPath.html'],
),
),
).toEqual([
{
fromRoutePath: '/some/path/suffix1',
toRoutePath: '/',
},
{
fromRoutePath: '/some/other/path/suffix2',
toRoutePath: '/',
},
{
fromRoutePath: '/testpath/some/path/suffix1',
toRoutePath: '/testpath',
},
{
fromRoutePath: '/testpath/some/other/path/suffix2',
toRoutePath: '/testpath',
},
{
fromRoutePath: '/otherPath.html/some/path/suffix1',
toRoutePath: '/otherPath.html',
},
{
fromRoutePath: '/otherPath.html/some/other/path/suffix2',
toRoutePath: '/otherPath.html',
},
]);
});
test('should filter unwanted redirects', () => {
expect(
collectRedirects(
createTestPluginContext(
{
fromExtensions: ['html', 'exe'],
toExtensions: ['html', 'exe'],
},
[
'/',
'/somePath',
'/somePath.html',
'/somePath.exe',
'/fromShouldWork.html',
'/toShouldWork',
],
),
),
).toEqual([
{
fromRoutePath: '/toShouldWork.html',
toRoutePath: '/toShouldWork',
},
{
fromRoutePath: '/toShouldWork.exe',
toRoutePath: '/toShouldWork',
},
{
fromRoutePath: '/fromShouldWork',
toRoutePath: '/fromShouldWork.html',
},
]);
});
});

View file

@ -44,11 +44,11 @@ const createExtensionValidationTests = (
});
};
describe('fromExtensionsRedirectCreator', () => {
createExtensionValidationTests(fromExtensionsRedirectCreator);
describe('toExtensionsRedirectCreator', () => {
createExtensionValidationTests(toExtensionsRedirectCreator);
test('should create redirects from html/htm extensions', () => {
const redirectCreator = fromExtensionsRedirectCreator(['html', 'htm']);
const redirectCreator = toExtensionsRedirectCreator(['html', 'htm']);
expect(redirectCreator('')).toEqual([]);
expect(redirectCreator('/')).toEqual([]);
expect(redirectCreator('/abc.html')).toEqual(['/abc']);
@ -57,18 +57,18 @@ describe('fromExtensionsRedirectCreator', () => {
});
test('should not create redirection for an empty extension array', () => {
const redirectCreator = fromExtensionsRedirectCreator([]);
const redirectCreator = toExtensionsRedirectCreator([]);
expect(redirectCreator('')).toEqual([]);
expect(redirectCreator('/')).toEqual([]);
expect(redirectCreator('/abc.html')).toEqual([]);
});
});
describe('toExtensionsRedirectCreator', () => {
createExtensionValidationTests(toExtensionsRedirectCreator);
describe('fromExtensionsRedirectCreator', () => {
createExtensionValidationTests(fromExtensionsRedirectCreator);
test('should create redirects to html/htm extensions', () => {
const redirectCreator = toExtensionsRedirectCreator(['html', 'htm']);
const redirectCreator = fromExtensionsRedirectCreator(['html', 'htm']);
expect(redirectCreator('')).toEqual([]);
expect(redirectCreator('/')).toEqual([]);
expect(redirectCreator('/abc')).toEqual(['/abc.html', '/abc.htm']);
@ -77,7 +77,7 @@ describe('toExtensionsRedirectCreator', () => {
});
test('should not create redirection for an empty extension array', () => {
const redirectCreator = toExtensionsRedirectCreator([]);
const redirectCreator = fromExtensionsRedirectCreator([]);
expect(redirectCreator('')).toEqual([]);
expect(redirectCreator('/')).toEqual([]);
expect(redirectCreator('/abc')).toEqual([]);

View file

@ -31,6 +31,8 @@ function filterUnwantedRedirects(
redirects: RedirectMetadata[],
pluginContext: PluginContext,
): RedirectMetadata[] {
// TODO how should we warn the user of filtered redirects?
// we don't want to create twice the same redirect
redirects = uniqBy(redirects, (redirect) => redirect.fromRoutePath);

View file

@ -23,7 +23,7 @@ export default function pluginClientRedirectsPages(
async postBuild(props: Props) {
const pluginContext: PluginContext = {
routesPaths: props.routesPaths,
siteConfig: props.siteConfig,
baseUrl: props.baseUrl,
outDir: props.outDir,
options,
};

View file

@ -38,7 +38,8 @@ const validateExtension = (ext: string) => {
const addLeadingDot = (extension: string) => `.${extension}`;
export function fromExtensionsRedirectCreator(
// Create new /path that redirects to existing an /path.html
export function toExtensionsRedirectCreator(
extensions: string[],
): RedirectsCreator {
extensions.forEach(validateExtension);
@ -60,7 +61,8 @@ export function fromExtensionsRedirectCreator(
};
}
export function toExtensionsRedirectCreator(
// Create new /path.html that redirects to existing an /path
export function fromExtensionsRedirectCreator(
extensions: string[],
): RedirectsCreator {
extensions.forEach(validateExtension);

View file

@ -15,24 +15,24 @@ export type PluginOptions = {
export type UserPluginOptions = Partial<PluginOptions>;
// The minimal infos the plugin needs to work
export type PluginContext = Pick<
Props,
'routesPaths' | 'outDir' | 'baseUrl'
> & {
options: PluginOptions;
};
// For a given existing route path,
// return all the paths from which we should redirect from
export type RedirectsCreator = (
routePath: string,
) => string[] | null | undefined;
// Having an in-memory representation of wanted redirects is easier to test
// In-memory representation of redirects we want: easier to test
// /!\ easy to be confused: "fromRoutePath" is the new page we should create,
// that redirects to "toRoutePath" the existing Docusaurus page
export type RedirectMetadata = {
fromRoutePath: string;
toRoutePath: string;
toUrl: string;
redirectPageContent: string;
redirectAbsoluteFilePath: string;
};
export type PluginContext = Pick<
Props,
'routesPaths' | 'siteConfig' | 'outDir'
> & {
options: PluginOptions;
};