docusaurus/packages/docusaurus-utils-validation/src/__tests__/validationSchemas.test.ts
ozaki c745021b01
feat(blog): add LastUpdateAuthor & LastUpdateTime (#9912)
Co-authored-by: OzakIOne <OzakIOne@users.noreply.github.com>
Co-authored-by: sebastien <lorber.sebastien@gmail.com>
2024-03-15 12:50:06 +01:00

244 lines
6.5 KiB
TypeScript

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import Joi from '../Joi';
import {
AdmonitionsSchema,
RehypePluginsSchema,
RemarkPluginsSchema,
PluginIdSchema,
URISchema,
PathnameSchema,
RouteBasePathSchema,
ContentVisibilitySchema,
FrontMatterLastUpdateSchema,
} from '../validationSchemas';
function createTestHelpers({
schema,
defaultValue,
}: {
schema: Joi.Schema;
defaultValue?: unknown;
}) {
function testOK(value: unknown, options?: {normalizedValue?: unknown}) {
const expectedValue = options?.normalizedValue ?? value ?? defaultValue;
expect(Joi.attempt(value, schema)).toEqual(expectedValue);
}
function testFail(value: unknown) {
expect(() => Joi.attempt(value, schema)).toThrowErrorMatchingSnapshot(
`for value=${JSON.stringify(value)}`,
);
}
return {testOK, testFail};
}
function testMarkdownPluginSchemas(schema: Joi.Schema) {
const {testOK, testFail} = createTestHelpers({
schema,
defaultValue: [],
});
testOK(undefined);
testOK([() => {}]);
testOK([[() => {}, {attr: 'val'}]]);
testOK([[() => {}, {attr: 'val'}], () => {}, [() => {}, {attr: 'val'}]]);
// cSpell:ignore remarkjs
// official `remarkjs/remark-frontmatter` plugin accepts string options
testOK([[() => {}, 'string-option']]);
testOK([[() => {}, true]]);
testFail(null);
testFail(false);
testFail(3);
testFail([null]);
testFail([false]);
testFail([3]);
testFail([[]]);
testFail([[() => {}, undefined]]);
}
describe('validation schemas', () => {
it('pluginIdSchema', () => {
const {testOK, testFail} = createTestHelpers({
schema: PluginIdSchema,
defaultValue: 'default',
});
testOK(undefined);
testOK('docs');
testOK('default');
testOK('plugin-id_with-simple-special-chars');
testOK('doc1');
testFail('/docs');
testFail('docs/');
testFail('do/cs');
testFail('do cs');
testFail(null);
testFail(3);
testFail(true);
testFail([]);
});
it('admonitionsSchema', () => {
const {testOK, testFail} = createTestHelpers({
schema: AdmonitionsSchema,
defaultValue: true,
});
testOK(undefined);
testOK(true);
testOK(false);
testOK({});
testOK({keywords: ['info', 'tip']});
testOK({keywords: ['info', 'tip'], extendDefaults: true});
testOK({keywords: ['info', 'tip'], extendDefaults: false});
testOK({keywords: []});
testOK({keywords: [], extendDefaults: true}); // noop
testOK({keywords: [], extendDefaults: false}); // disable admonitions
testOK({keywords: ['custom-keyword'], extendDefaults: true});
testOK({keywords: ['custom-keyword'], extendDefaults: false});
testFail(3);
testFail([]);
testFail({unknownAttribute: 'val'});
testFail({tag: ''});
testFail({keywords: ['custom-keyword'], extendDefaults: 42});
testFail({tag: '+++'});
testFail({tag: '+++', keywords: ['info', 'tip']});
// Legacy types
testFail({
infima: true,
});
testFail({
icons: 'emoji',
});
testFail({
customTypes: {
myKeyword: {
keyword: `myKeyword`,
infima: true,
svg: '<svg width="512px" height="512px" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"></svg>',
},
},
});
});
it('remarkPluginsSchema', () => {
testMarkdownPluginSchemas(RemarkPluginsSchema);
});
it('rehypePluginsSchema', () => {
testMarkdownPluginSchemas(RehypePluginsSchema);
});
it('uRISchema', () => {
const {testFail, testOK} = createTestHelpers({schema: URISchema});
const validURL = 'https://docusaurus.io';
const doubleHash = 'https://docusaurus.io#github#/:';
const invalidURL = 'spaces are invalid in a URL';
const relativeURL = 'relativeURL';
const relativeURLWithParent = '../relativeURLWithParent';
const urlFromIssue = 'https://riot.im/app/#/room/#ligo-public:matrix.org';
testOK(validURL);
testOK(doubleHash);
testFail(invalidURL);
testOK(relativeURL);
testOK(relativeURLWithParent);
testOK(urlFromIssue);
const protocolRelativeUrl1 = '//docusaurus.io/path';
const protocolRelativeUrl2 = '//docusaurus.io/docs/doc1#hash';
testOK(protocolRelativeUrl1);
testOK(protocolRelativeUrl2);
});
it('pathnameSchema', () => {
const {testFail, testOK} = createTestHelpers({schema: PathnameSchema});
testOK('/foo');
testFail('foo');
testFail('https://github.com/foo');
});
it('routeBasePathSchema', () => {
const {testFail, testOK} = createTestHelpers({
schema: RouteBasePathSchema,
defaultValue: undefined,
});
testOK('', {normalizedValue: '/'});
testOK('/');
testOK('/foo', {normalizedValue: '/foo'});
testOK('foo', {normalizedValue: '/foo'});
testOK('blog', {normalizedValue: '/blog'});
testOK('blog/', {normalizedValue: '/blog/'});
testOK('prefix/blog', {normalizedValue: '/prefix/blog'});
testOK('prefix/blog/', {normalizedValue: '/prefix/blog/'});
testOK('/prefix/blog', {normalizedValue: '/prefix/blog'});
testOK(undefined);
testFail(3);
testFail([]);
testFail(null);
testFail({});
});
it('contentVisibilitySchema', () => {
const {testFail, testOK} = createTestHelpers({
schema: ContentVisibilitySchema,
});
testOK({});
testOK({draft: false});
testOK({draft: true});
testOK({unlisted: false});
testOK({unlisted: true});
testOK({draft: false, unlisted: false});
testOK({draft: true, unlisted: false});
testOK({draft: false, unlisted: true});
testOK({draft: true, unlisted: undefined});
testOK({draft: undefined, unlisted: true});
testFail({draft: 'bad string'});
testFail({draft: 42});
testFail({unlisted: 'bad string'});
testFail({unlisted: 42});
testFail({draft: true, unlisted: true});
});
it('frontMatterLastUpdateSchema schema', () => {
const {testFail, testOK} = createTestHelpers({
schema: FrontMatterLastUpdateSchema,
});
testOK(undefined);
testOK({date: '2021-01-01'});
testOK({date: '2021-01'});
testOK({date: '2021'});
testOK({date: new Date()});
testOK({author: 'author'});
testOK({author: 'author', date: '2021-01-01'});
testOK({author: 'author', date: new Date()});
testFail(null);
testFail({});
testFail('string');
testFail(42);
testFail(true);
testFail([]);
testFail({author: 23});
testFail({date: '20-20-20'});
});
});