From abda30d336fb2fb79b401c0b02a9aa174174bdfa Mon Sep 17 00:00:00 2001 From: Koy Date: Fri, 26 Feb 2021 19:23:03 +0800 Subject: [PATCH] test(unit): add test cases on isExternal. (#1515) * test(unit): add test cases on xss. --- src/core/fetch/index.js | 28 +---------------- src/core/util/core.js | 32 +++++++++++++++++++ test/unit/core-util.test.js | 63 +++++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 27 deletions(-) create mode 100644 test/unit/core-util.test.js diff --git a/src/core/fetch/index.js b/src/core/fetch/index.js index 2d6f813c2..f0f288798 100644 --- a/src/core/fetch/index.js +++ b/src/core/fetch/index.js @@ -1,7 +1,7 @@ /* eslint-disable no-unused-vars */ import { callHook } from '../init/lifecycle'; import { getParentPath, stringifyQuery } from '../router/util'; -import { noop } from '../util/core'; +import { noop, isExternal } from '../util/core'; import { getAndActive } from '../event/sidebar'; import { get } from './ajax'; @@ -20,32 +20,6 @@ function loadNested(path, qs, file, next, vm, first) { ).then(next, _ => loadNested(path, qs, file, next, vm)); } -function isExternal(url) { - let match = url.match( - /^([^:/?#]+:)?(?:\/{2,}([^/?#]*))?([^?#]+)?(\?[^#]*)?(#.*)?/ - ); - if ( - typeof match[1] === 'string' && - match[1].length > 0 && - match[1].toLowerCase() !== location.protocol - ) { - return true; - } - if ( - typeof match[2] === 'string' && - match[2].length > 0 && - match[2].replace( - new RegExp( - ':(' + { 'http:': 80, 'https:': 443 }[location.protocol] + ')?$' - ), - '' - ) !== location.host - ) { - return true; - } - return false; -} - export function fetchMixin(proto) { let last; diff --git a/src/core/util/core.js b/src/core/util/core.js index 9d2638412..50b7ed02c 100644 --- a/src/core/util/core.js +++ b/src/core/util/core.js @@ -66,3 +66,35 @@ export function noop() {} export function isFn(obj) { return typeof obj === 'function'; } + +/** + * Check if url is external + * @param {String} string url + * @returns {Boolean} True if the passed-in url is external + */ +export function isExternal(url) { + let match = url.match( + /^([^:/?#]+:)?(?:\/{2,}([^/?#]*))?([^?#]+)?(\?[^#]*)?(#.*)?/ + ); + + if ( + typeof match[1] === 'string' && + match[1].length > 0 && + match[1].toLowerCase() !== location.protocol + ) { + return true; + } + if ( + typeof match[2] === 'string' && + match[2].length > 0 && + match[2].replace( + new RegExp( + ':(' + { 'http:': 80, 'https:': 443 }[location.protocol] + ')?$' + ), + '' + ) !== location.host + ) { + return true; + } + return false; +} diff --git a/test/unit/core-util.test.js b/test/unit/core-util.test.js new file mode 100644 index 000000000..0ebbf7bbd --- /dev/null +++ b/test/unit/core-util.test.js @@ -0,0 +1,63 @@ +const { isExternal } = require('../../src/core/util'); + +// Core util +// ----------------------------------------------------------------------------- +describe('core/util', () => { + // isExternal() + // --------------------------------------------------------------------------- + describe('isExternal()', () => { + // cases non external + test('non external local url with one /', () => { + const result = isExternal(`/${location.host}/docsify/demo.md`); + + expect(result).toBeFalsy(); + }); + + test('non external local url with two //', () => { + const result = isExternal(`//${location.host}/docsify/demo.md`); + + expect(result).toBeFalsy(); + }); + + test('non external local url with three ///', () => { + const result = isExternal(`///${location.host}/docsify/demo.md`); + + expect(result).toBeFalsy(); + }); + + test('non external local url with more /', () => { + const result = isExternal( + `//////////////////${location.host}/docsify/demo.md` + ); + + expect(result).toBeFalsy(); + }); + + test('non external url with one /', () => { + const result = isExternal('/example.github.io/docsify/demo.md'); + + expect(result).toBeFalsy(); + }); + + // cases is external + test('external url with two //', () => { + const result = isExternal('/docsify/demo.md'); + + expect(result).toBeFalsy(); + }); + + test('external url with three ///', () => { + const result = isExternal('///example.github.io/docsify/demo.md'); + + expect(result).toBeTruthy(); + }); + + test('external url with more /', () => { + const result = isExternal( + '//////////////////example.github.io/docsify/demo.md' + ); + + expect(result).toBeTruthy(); + }); + }); +});