blob: b788b172f529d2e3e45240200354a64b2b88cee9 [file] [log] [blame]
// 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&amp;hl=en">' +
'http://lascap:p4ssw0rd@google.com:80/s?q=a&amp;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&amp;c=d&amp;e=f">' +
'http://google.com/?a=b&amp;c=d&amp;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&amp;hl=en">' +
'http://66.102.7.104/search?q=cache:I4LoMT6euUUJ:' +
'www.google.com/intl/en/help/features.html+google+cache&amp;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',
'&lt;script&gt;malicious_code()&lt;/script&gt;\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',
'&lt;script&gt;malicious_code()&lt;/script&gt;\u2029Vanilla text');
}
function testJsInjectionWithIgnorableNonTagChar() {
assertLinkify(
'Angle brackets are normalized even when followed by an ignorable ' +
'non-tag character.',
'<\u0000img onerror=alert(1337) src=\n>',
'&lt;&#0;img onerror=alert(1337) src=\n&gt;');
}
function testJsInjectionWithTextarea() {
assertLinkify(
'Putting the result in a textarea can\'t cause other textarea text to ' +
'be treated as tag content.',
'</textarea',
'&lt;/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>>',
'&lt;&lt;br&gt;script&lt;br&gt;&gt;alert(1337)&lt;&lt;br&gt;/&lt;' +
'br&gt;script&lt;br&gt;&gt;');
}
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 &lt;class&gt; 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 &lt;<a href="http://www.google.com/">' +
'http://www.google.com/<\/a>&gt;');
}
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 &lt;<a href="http://www.google.com/">' +
'http://www.google.com/<\/a>&gt;, 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>!');
}