456 lines
16 KiB
JavaScript
456 lines
16 KiB
JavaScript
// Copyright 2008 The Closure Library Authors. All Rights Reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS-IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
goog.provide('goog.string.linkifyTest');
|
|
goog.setTestOnly('goog.string.linkifyTest');
|
|
|
|
goog.require('goog.string');
|
|
goog.require('goog.string.linkify');
|
|
goog.require('goog.testing.dom');
|
|
goog.require('goog.testing.jsunit');
|
|
|
|
var div = document.createElement('div');
|
|
|
|
function assertLinkify(comment, input, expected) {
|
|
assertEquals(
|
|
comment, expected,
|
|
goog.string.linkify.linkifyPlainText(input, {rel: '', target: ''}));
|
|
}
|
|
|
|
function testContainsNoLink() {
|
|
assertLinkify(
|
|
'Text does not contain any links',
|
|
'Text with no links in it.',
|
|
'Text with no links in it.');
|
|
}
|
|
|
|
function testContainsALink() {
|
|
assertLinkify(
|
|
'Text only contains a link',
|
|
'http://www.google.com/',
|
|
'<a href="http://www.google.com/">http://www.google.com/<\/a>');
|
|
}
|
|
|
|
function testStartsWithALink() {
|
|
assertLinkify(
|
|
'Text starts with a link',
|
|
'http://www.google.com/ is a well known search engine',
|
|
'<a href="http://www.google.com/">http://www.google.com/<\/a>' +
|
|
' is a well known search engine');
|
|
}
|
|
|
|
function testEndsWithALink() {
|
|
assertLinkify(
|
|
'Text ends with a link',
|
|
'Look at this search engine: http://www.google.com/',
|
|
'Look at this search engine: ' +
|
|
'<a href="http://www.google.com/">http://www.google.com/<\/a>');
|
|
}
|
|
|
|
function testContainsOnlyEmail() {
|
|
assertLinkify(
|
|
'Text only contains an email address',
|
|
'bolinfest@google.com',
|
|
'<a href="mailto:bolinfest@google.com">bolinfest@google.com<\/a>');
|
|
}
|
|
|
|
function testStartsWithAnEmail() {
|
|
assertLinkify(
|
|
'Text starts with an email address',
|
|
'bolinfest@google.com wrote this test.',
|
|
'<a href="mailto:bolinfest@google.com">bolinfest@google.com<\/a>' +
|
|
' wrote this test.');
|
|
}
|
|
|
|
function testEndsWithAnEmail() {
|
|
assertLinkify(
|
|
'Text ends with an email address',
|
|
'This test was written by bolinfest@google.com.',
|
|
'This test was written by ' +
|
|
'<a href="mailto:bolinfest@google.com">bolinfest@google.com<\/a>.');
|
|
}
|
|
|
|
function testUrlWithPortNumber() {
|
|
assertLinkify(
|
|
'URL with a port number',
|
|
'http://www.google.com:80/',
|
|
'<a href="http://www.google.com:80/">http://www.google.com:80/<\/a>');
|
|
}
|
|
|
|
function testUrlWithUserPasswordAndPortNumber() {
|
|
assertLinkify(
|
|
'URL with a user, a password and a port number',
|
|
'http://lascap:p4ssw0rd@google.com:80/s?q=a&hl=en',
|
|
'<a href="http://lascap:p4ssw0rd@google.com:80/s?q=a&hl=en">' +
|
|
'http://lascap:p4ssw0rd@google.com:80/s?q=a&hl=en<\/a>');
|
|
}
|
|
|
|
function testUrlWithUnderscore() {
|
|
assertLinkify(
|
|
'URL with an underscore',
|
|
'http://www_foo.google.com/',
|
|
'<a href="http://www_foo.google.com/">http://www_foo.google.com/<\/a>');
|
|
}
|
|
|
|
function testInternalUrlWithoutDomain() {
|
|
assertLinkify(
|
|
'Internal URL without a proper domain',
|
|
'http://tracker/1068594',
|
|
'<a href="http://tracker/1068594">http://tracker/1068594<\/a>');
|
|
}
|
|
|
|
function testInternalUrlOneChar() {
|
|
assertLinkify(
|
|
'Internal URL with a one char domain',
|
|
'http://b',
|
|
'<a href="http://b">http://b<\/a>');
|
|
}
|
|
|
|
function testSecureInternalUrlWithoutDomain() {
|
|
assertLinkify(
|
|
'Secure Internal URL without a proper domain',
|
|
'https://review/6594805',
|
|
'<a href="https://review/6594805">https://review/6594805<\/a>');
|
|
}
|
|
|
|
function testTwoUrls() {
|
|
assertLinkify(
|
|
'Text with two URLs in it',
|
|
'I use both http://www.google.com and http://yahoo.com, don\'t you?',
|
|
'I use both <a href="http://www.google.com">http://www.google.com<\/a> ' +
|
|
'and <a href="http://yahoo.com">http://yahoo.com<\/a>, ' +
|
|
goog.string.htmlEscape('don\'t you?'));
|
|
}
|
|
|
|
function testGetParams() {
|
|
assertLinkify(
|
|
'URL with GET params',
|
|
'http://google.com/?a=b&c=d&e=f',
|
|
'<a href="http://google.com/?a=b&c=d&e=f">' +
|
|
'http://google.com/?a=b&c=d&e=f<\/a>');
|
|
}
|
|
|
|
function testGoogleCache() {
|
|
assertLinkify(
|
|
'Google search result from cache',
|
|
'http://66.102.7.104/search?q=cache:I4LoMT6euUUJ:' +
|
|
'www.google.com/intl/en/help/features.html+google+cache&hl=en',
|
|
'<a href="http://66.102.7.104/search?q=cache:I4LoMT6euUUJ:' +
|
|
'www.google.com/intl/en/help/features.html+google+cache&hl=en">' +
|
|
'http://66.102.7.104/search?q=cache:I4LoMT6euUUJ:' +
|
|
'www.google.com/intl/en/help/features.html+google+cache&hl=en' +
|
|
'<\/a>');
|
|
}
|
|
|
|
function testUrlWithoutHttp() {
|
|
assertLinkify(
|
|
'URL without http protocol',
|
|
'It\'s faster to type www.google.com without the http:// in front.',
|
|
goog.string.htmlEscape('It\'s faster to type ') +
|
|
'<a href="http://www.google.com">www.google.com' +
|
|
'<\/a> without the http:// in front.');
|
|
}
|
|
|
|
function testUrlWithCapitalsWithoutHttp() {
|
|
assertLinkify(
|
|
'URL with capital letters without http protocol',
|
|
'It\'s faster to type Www.google.com without the http:// in front.',
|
|
goog.string.htmlEscape('It\'s faster to type ') +
|
|
'<a href="http://Www.google.com">Www.google.com' +
|
|
'<\/a> without the http:// in front.');
|
|
}
|
|
|
|
function testUrlHashBang() {
|
|
assertLinkify(
|
|
'URL with #!',
|
|
'Another test URL: ' +
|
|
'https://www.google.com/testurls/#!/page',
|
|
'Another test URL: ' +
|
|
'<a href="https://www.google.com/testurls/#!/page">' +
|
|
'https://www.google.com/testurls/#!/page<\/a>');
|
|
}
|
|
|
|
function testTextLooksLikeUrlWithoutHttp() {
|
|
assertLinkify(
|
|
'Text looks like an url but is not',
|
|
'This showww.is just great: www.is',
|
|
'This showww.is just great: <a href="http://www.is">www.is<\/a>');
|
|
}
|
|
|
|
function testEmailWithSubdomain() {
|
|
assertLinkify(
|
|
'Email with a subdomain',
|
|
'Send mail to bolinfest@groups.google.com.',
|
|
'Send mail to <a href="mailto:bolinfest@groups.google.com">' +
|
|
'bolinfest@groups.google.com<\/a>.');
|
|
}
|
|
|
|
function testEmailWithHyphen() {
|
|
assertLinkify(
|
|
'Email with a hyphen in the domain name',
|
|
'Send mail to bolinfest@google-groups.com.',
|
|
'Send mail to <a href="mailto:bolinfest@google-groups.com">' +
|
|
'bolinfest@google-groups.com<\/a>.');
|
|
}
|
|
|
|
function testEmailUsernameWithSpecialChars() {
|
|
assertLinkify(
|
|
'Email with a hyphen, period, and + in the user name',
|
|
'Send mail to bolin-fest+for.um@google.com',
|
|
'Send mail to <a href="mailto:bolin-fest+for.um@google.com">' +
|
|
'bolin-fest+for.um@google.com<\/a>');
|
|
}
|
|
|
|
function testEmailWithUnderscoreInvalid() {
|
|
assertLinkify(
|
|
'Email with an underscore in the domain name, which is invalid',
|
|
'Do not email bolinfest@google_groups.com.',
|
|
'Do not email bolinfest@google_groups.com.');
|
|
}
|
|
|
|
function testUrlNotHttp() {
|
|
assertLinkify(
|
|
'Url using unusual scheme',
|
|
'Looking for some goodies: ftp://ftp.google.com/goodstuff/',
|
|
'Looking for some goodies: ' +
|
|
'<a href="ftp://ftp.google.com/goodstuff/">' +
|
|
'ftp://ftp.google.com/goodstuff/<\/a>');
|
|
}
|
|
|
|
function testJsInjection() {
|
|
assertLinkify(
|
|
'Text includes some javascript',
|
|
'Welcome in hell <script>alert(\'this is hell\')<\/script>',
|
|
goog.string.htmlEscape(
|
|
'Welcome in hell <script>alert(\'this is hell\')<\/script>'));
|
|
}
|
|
|
|
function testJsInjectionDotIsBlind() {
|
|
assertLinkify(
|
|
'Javascript injection using regex . blindness to newline chars',
|
|
'<script>malicious_code()<\/script>\nVery nice url: www.google.com',
|
|
'<script>malicious_code()</script>\nVery nice url: ' +
|
|
'<a href="http://www.google.com">www.google.com<\/a>');
|
|
}
|
|
|
|
function testJsInjectionWithUnicodeLineReturn() {
|
|
assertLinkify(
|
|
'Javascript injection using regex . blindness to newline chars with a ' +
|
|
'unicode newline character.',
|
|
'<script>malicious_code()<\/script>\u2029Vanilla text',
|
|
'<script>malicious_code()</script>\u2029Vanilla text');
|
|
}
|
|
|
|
function testJsInjectionWithIgnorableNonTagChar() {
|
|
assertLinkify(
|
|
'Angle brackets are normalized even when followed by an ignorable ' +
|
|
'non-tag character.',
|
|
'<\u0000img onerror=alert(1337) src=\n>',
|
|
'<�img onerror=alert(1337) src=\n>');
|
|
}
|
|
|
|
function testJsInjectionWithTextarea() {
|
|
assertLinkify(
|
|
'Putting the result in a textarea can\'t cause other textarea text to ' +
|
|
'be treated as tag content.',
|
|
'</textarea',
|
|
'</textarea');
|
|
}
|
|
|
|
function testJsInjectionWithNewlineConversion() {
|
|
assertLinkify(
|
|
'Any newline conversion and whitespace normalization won\'t cause tag ' +
|
|
'parts to be recombined.',
|
|
'<<br>script<br>>alert(1337)<<br>/<br>script<br>>',
|
|
'<<br>script<br>>alert(1337)<<br>/<' +
|
|
'br>script<br>>');
|
|
}
|
|
|
|
function testNoProtocolBlacklisting() {
|
|
assertLinkify(
|
|
'No protocol blacklisting.',
|
|
'Click: jscript:alert%281337%29\nClick: JSscript:alert%281337%29\n' +
|
|
'Click: VBscript:alert%281337%29\nClick: Script:alert%281337%29\n' +
|
|
'Click: flavascript:alert%281337%29',
|
|
'Click: jscript:alert%281337%29\nClick: JSscript:alert%281337%29\n' +
|
|
'Click: VBscript:alert%281337%29\nClick: Script:alert%281337%29\n' +
|
|
'Click: flavascript:alert%281337%29');
|
|
}
|
|
|
|
function testProtocolWhitelistingEffective() {
|
|
assertLinkify(
|
|
'Protocol whitelisting is effective.',
|
|
'Click httpscript:alert%281337%29\nClick mailtoscript:alert%281337%29\n' +
|
|
'Click j\u00A0avascript:alert%281337%29\n' +
|
|
'Click \u00A0javascript:alert%281337%29',
|
|
'Click httpscript:alert%281337%29\nClick mailtoscript:alert%281337%29\n' +
|
|
'Click j\u00A0avascript:alert%281337%29\n' +
|
|
'Click \u00A0javascript:alert%281337%29');
|
|
}
|
|
|
|
function testLinkifyNoOptions() {
|
|
div.innerHTML = goog.string.linkify.linkifyPlainText('http://www.google.com');
|
|
goog.testing.dom.assertHtmlContentsMatch(
|
|
'<a href="http://www.google.com" target="_blank" rel="nofollow">' +
|
|
'http://www.google.com<\/a>',
|
|
div, true /* opt_strictAttributes */);
|
|
}
|
|
|
|
function testLinkifyOptionsNoAttributes() {
|
|
div.innerHTML = goog.string.linkify.linkifyPlainText(
|
|
'The link for www.google.com is located somewhere in ' +
|
|
'https://www.google.fr/?hl=en, you should find it easily.',
|
|
{rel: '', target: ''});
|
|
goog.testing.dom.assertHtmlContentsMatch(
|
|
'The link for <a href="http://www.google.com">www.google.com<\/a> is ' +
|
|
'located somewhere in ' +
|
|
'<a href="https://www.google.fr/?hl=en">https://www.google.fr/?hl=en' +
|
|
'<\/a>, you should find it easily.',
|
|
div, true /* opt_strictAttributes */);
|
|
}
|
|
|
|
function testLinkifyOptionsClassName() {
|
|
div.innerHTML = goog.string.linkify.linkifyPlainText(
|
|
'Attribute with <class> name www.w3c.org.',
|
|
{'class': 'link-added'});
|
|
goog.testing.dom.assertHtmlContentsMatch(
|
|
'Attribute with <class> name <a href="http://www.w3c.org" ' +
|
|
'target="_blank" rel="nofollow" class="link-added">www.w3c.org<\/a>.',
|
|
div, true /* opt_strictAttributes */);
|
|
}
|
|
|
|
function testFindFirstUrlNoScheme() {
|
|
assertEquals('www.google.com', goog.string.linkify.findFirstUrl(
|
|
'www.google.com'));
|
|
}
|
|
|
|
function testFindFirstUrlNoSchemeWithText() {
|
|
assertEquals('www.google.com', goog.string.linkify.findFirstUrl(
|
|
'prefix www.google.com something'));
|
|
}
|
|
|
|
function testFindFirstUrlScheme() {
|
|
assertEquals('http://www.google.com', goog.string.linkify.findFirstUrl(
|
|
'http://www.google.com'));
|
|
}
|
|
|
|
function testFindFirstUrlSchemeWithText() {
|
|
assertEquals('http://www.google.com', goog.string.linkify.findFirstUrl(
|
|
'prefix http://www.google.com something'));
|
|
}
|
|
|
|
function testFindFirstUrlNoUrl() {
|
|
assertEquals('', goog.string.linkify.findFirstUrl(
|
|
'ygvtfr676 5v68fk uygbt85F^&%^&I%FVvc .'));
|
|
}
|
|
|
|
function testFindFirstEmailNoScheme() {
|
|
assertEquals('fake@google.com', goog.string.linkify.findFirstEmail(
|
|
'fake@google.com'));
|
|
}
|
|
|
|
function testFindFirstEmailNoSchemeWithText() {
|
|
assertEquals('fake@google.com', goog.string.linkify.findFirstEmail(
|
|
'prefix fake@google.com something'));
|
|
}
|
|
|
|
function testFindFirstEmailScheme() {
|
|
assertEquals('mailto:fake@google.com', goog.string.linkify.findFirstEmail(
|
|
'mailto:fake@google.com'));
|
|
}
|
|
|
|
function testFindFirstEmailSchemeWithText() {
|
|
assertEquals('mailto:fake@google.com', goog.string.linkify.findFirstEmail(
|
|
'prefix mailto:fake@google.com something'));
|
|
}
|
|
|
|
function testFindFirstEmailNoUrl() {
|
|
assertEquals('', goog.string.linkify.findFirstEmail(
|
|
'ygvtfr676 5v68fk uygbt85F^&%^&I%FVvc .'));
|
|
}
|
|
|
|
function testContainsPunctuation_parens() {
|
|
assertLinkify(
|
|
'Link contains parens, but does not end with them',
|
|
'www.google.com/abc(v1).html',
|
|
'<a href="http://www.google.com/abc(v1).html">' +
|
|
'www.google.com/abc(v1).html<\/a>');
|
|
}
|
|
|
|
function testEndsWithPunctuation() {
|
|
assertLinkify(
|
|
'Link ends with punctuation',
|
|
'Have you seen www.google.com? It\'s awesome.',
|
|
'Have you seen <a href="http://www.google.com">www.google.com<\/a>?' +
|
|
goog.string.htmlEscape(' It\'s awesome.'));
|
|
}
|
|
|
|
function testEndsWithPunctuation_closeParen() {
|
|
assertLinkify(
|
|
'Link inside parentheses',
|
|
'(For more info see www.googl.com)',
|
|
'(For more info see <a href="http://www.googl.com">www.googl.com<\/a>)');
|
|
assertLinkify(
|
|
'Parentheses inside link',
|
|
'http://en.wikipedia.org/wiki/Titanic_(1997_film)',
|
|
'<a href="http://en.wikipedia.org/wiki/Titanic_(1997_film)">' +
|
|
'http://en.wikipedia.org/wiki/Titanic_(1997_film)<\/a>');
|
|
}
|
|
|
|
function testEndsWithPunctuation_openParen() {
|
|
assertLinkify(
|
|
'Link followed by open parenthesis',
|
|
'www.google.com(',
|
|
'<a href="http://www.google.com(">www.google.com(<\/a>');
|
|
}
|
|
|
|
function testEndsWithPunctuation_angles() {
|
|
assertLinkify(
|
|
'Link inside angled brackets',
|
|
'Here is a bibliography entry <http://www.google.com/>',
|
|
'Here is a bibliography entry <<a href="http://www.google.com/">' +
|
|
'http://www.google.com/<\/a>>');
|
|
}
|
|
|
|
function testEndsWithPunctuation_closingPairThenSingle() {
|
|
assertLinkify(
|
|
'Link followed by closing punctuation pair then singular punctuation',
|
|
'Here is a bibliography entry <http://www.google.com/>, PTAL.',
|
|
'Here is a bibliography entry <<a href="http://www.google.com/">' +
|
|
'http://www.google.com/<\/a>>, PTAL.');
|
|
}
|
|
|
|
function testEndsWithPunctuation_ellipses() {
|
|
assertLinkify(
|
|
'Link followed by three dots',
|
|
'just look it up on www.google.com...',
|
|
'just look it up on <a href="http://www.google.com">www.google.com' +
|
|
'<\/a>...');
|
|
}
|
|
|
|
function testBracketsInUrl() {
|
|
assertLinkify(
|
|
'Link containing brackets',
|
|
'before http://google.com/details?answer[0]=42 after',
|
|
'before <a href="http://google.com/details?answer[0]=42">' +
|
|
'http://google.com/details?answer[0]=42<\/a> after');
|
|
}
|
|
|
|
function testUrlWithExclamation() {
|
|
assertLinkify(
|
|
'URL with exclamation points',
|
|
'This is awesome www.google.com!',
|
|
'This is awesome <a href="http://www.google.com">www.google.com<\/a>!');
|
|
}
|