goog.window.window_test.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of google-closure-library
Show all versions of google-closure-library
The Google Closure Library is a collection of JavaScript code
designed for use with the Google Closure JavaScript Compiler.
This non-official distribution was prepared by the ClojureScript
team at http://clojure.org/
// Copyright 2009 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.windowTest');
goog.setTestOnly('goog.windowTest');
goog.require('goog.Promise');
goog.require('goog.dom');
goog.require('goog.dom.TagName');
goog.require('goog.events');
goog.require('goog.functions');
goog.require('goog.html.SafeUrl');
goog.require('goog.labs.userAgent.browser');
goog.require('goog.labs.userAgent.engine');
goog.require('goog.labs.userAgent.platform');
goog.require('goog.string');
goog.require('goog.testing.PropertyReplacer');
goog.require('goog.testing.TestCase');
goog.require('goog.testing.jsunit');
goog.require('goog.window');
var newWin;
var REDIRECT_URL_PREFIX = 'window_test.html?runTests=';
var WIN_LOAD_TRY_TIMEOUT = 100;
var MAX_WIN_LOAD_TRIES = 50; // 50x100ms = 5s waiting for window to load.
var stubs = new goog.testing.PropertyReplacer();
function shouldRunTests() {
// MS Edge has a bunch of flaky test failures around window.open.
// TODO(joeltine): Remove this when http://b/25455129 is fixed.
return !goog.labs.userAgent.browser.isEdge();
}
function setUpPage() {
var anchors = goog.dom.getElementsByTagNameAndClass(
goog.dom.TagName.DIV, 'goog-like-link');
for (var i = 0; i < anchors.length; i++) {
goog.events.listen(anchors[i], 'click', function(e) {
goog.window.open(goog.dom.getTextContent(e.target), {'noreferrer': true});
});
}
goog.testing.TestCase.getActiveTestCase().promiseTimeout = 60000; // 60s
}
// To test goog.window.open we open a new window with this file again. Once
// the new window parses this file it sets this variable to true, indicating
// that the parent test may check window properties like referrer and location.
var newWinLoaded = true;
function setUp() {
newWin = undefined;
}
function tearDown() {
if (newWin) {
newWin.close();
}
stubs.reset();
}
/**
* Uses setTimeout to poll a new window for the "newWinLoaded" variable, which
* is set once the JavaScript is evaluated in that window.
*
* @param {Window} win
* @return {!goog.Promise} Promise for a window that resolves once the
* window has loaded.
*/
function waitForTestWindow(win) {
return new goog.Promise(function(resolve, reject) {
var checkWindow = function(numTries) {
if (!win) {
fail('Could not open new window. Check if popup blocker is enabled.');
}
if (numTries > MAX_WIN_LOAD_TRIES) {
fail('Window did not load after maximum number of checks.');
}
if (win.newWinLoaded) {
resolve(win);
} else {
window.setTimeout(checkWindow, WIN_LOAD_TRY_TIMEOUT);
}
};
checkWindow(0);
});
}
/**
* Opens a window and then verifies that the new window has the expected
* properties.
*
* @param {boolean} noreferrer Whether to test the noreferrer option.
* @param {string} urlParam Url param to append to the url being opened.
* @param {boolean} encodeUrlParam_opt Whether to percent-encode urlParam. This
* is needed because IE will not encode it automatically like other browsers
* browser and the Closure test server will 400 on certain characters in
* the URL (like '<' and '"').
* @return {!goog.Promise} Promise that resolves once the test is complete.
*/
function doTestOpenWindow(noreferrer, urlParam, encodeUrlParam_opt) {
if (encodeUrlParam_opt) {
urlParam = encodeURIComponent(urlParam);
}
// TODO(user): target is set because goog.window.open() will currently
// allow it to be undefined, which in IE seems to result in the same window
// being reused, instead of a new one being created. If goog.window.open()
// is fixed to use "_blank" by default then target can be removed here.
newWin = goog.window.open(
REDIRECT_URL_PREFIX + urlParam,
{'noreferrer': noreferrer, 'target': '_blank'});
return waitForTestWindow(newWin).then(function(win) {
verifyWindow(win, noreferrer, urlParam);
});
}
/**
* Asserts that a newly created window has the correct parameters.
*
* @param {Window} win
* @param {boolean} noreferrer Whether the noreferrer option is being tested.
* @param {string} urlParam Url param appended to the url being opened.
*/
function verifyWindow(win, noreferrer, urlParam) {
if (noreferrer) {
assertEquals(
'Referrer should have been stripped', '', win.document.referrer);
}
var winUrl = decodeURI(win.location);
var expectedUrlSuffix = decodeURI(urlParam);
assertTrue(
'New window href should have ended with <' + expectedUrlSuffix +
'> but was <' + winUrl + '>',
goog.string.endsWith(winUrl, expectedUrlSuffix));
}
function testOpenNotEncoded() {
return doTestOpenWindow(false, 'bogus~');
}
function testOpenEncoded() {
return doTestOpenWindow(false, 'bogus%7E');
}
function testOpenEncodedPercent() {
// Intent of url is to pass %7E to the server, so it was encoded to %257E .
return doTestOpenWindow(false, 'bogus%257E');
}
function testOpenNotEncodedHidingReferrer() {
return doTestOpenWindow(true, 'bogus~');
}
function testOpenEncodedHidingReferrer() {
return doTestOpenWindow(true, 'bogus%7E');
}
function testOpenEncodedPercentHidingReferrer() {
// Intent of url is to pass %7E to the server, so it was encoded to %257E .
return doTestOpenWindow(true, 'bogus%257E');
}
function testOpenSemicolon() {
return doTestOpenWindow(true, 'beforesemi;aftersemi');
}
function testTwoSemicolons() {
return doTestOpenWindow(true, 'a;b;c');
}
function testOpenAmpersand() {
return doTestOpenWindow(true, 'this&that');
}
function testOpenSingleQuote() {
return doTestOpenWindow(true, "'");
}
function testOpenDoubleQuote() {
return doTestOpenWindow(true, '"', goog.labs.userAgent.browser.isIE());
}
function testOpenTag() {
return doTestOpenWindow(true, '<', goog.labs.userAgent.browser.isIE());
}
function testOpenWindowSanitization() {
var navigatedUrl;
var mockWin = {open: function(url) { navigatedUrl = url; }};
goog.window.open('javascript:evil();', {}, mockWin);
assertEquals(goog.html.SafeUrl.INNOCUOUS_STRING, navigatedUrl);
// Try the other code path
goog.window.open({href: 'javascript:evil();'}, {}, mockWin);
assertEquals(goog.html.SafeUrl.INNOCUOUS_STRING, navigatedUrl);
goog.window.open('javascript:\'\'', {}, mockWin);
assertEquals(goog.html.SafeUrl.INNOCUOUS_STRING, navigatedUrl);
goog.window.open('about:blank', {}, mockWin);
assertEquals(goog.html.SafeUrl.INNOCUOUS_STRING, navigatedUrl);
}
function testOpenWindowNoSanitization() {
var navigatedUrl;
var mockWin = {open: function(url) { navigatedUrl = url; }};
goog.window.open('', {}, mockWin);
assertEquals('', navigatedUrl);
goog.window.open(goog.html.SafeUrl.ABOUT_BLANK, {}, mockWin);
assertEquals('about:blank', navigatedUrl);
}
function testOpenBlank() {
newWin = goog.window.openBlank('Loading...');
var urlParam = 'bogus~';
newWin.location.href = REDIRECT_URL_PREFIX + urlParam;
return waitForTestWindow(newWin).then(function() {
verifyWindow(newWin, false, urlParam);
});
}
function testOpenBlankReturnsNullPopupBlocker() {
var mockWin = {
// emulate popup-blocker by returning a null window on open().
open: function() { return null; }
};
var win = goog.window.openBlank('', {noreferrer: true}, mockWin);
assertNull(win);
}
function testOpenBlankEscapesSafely() {
// Opening a window with javascript: and then reading from its document.body
// is problematic because in some browsers the document.body won't have been
// updated yet, and in some IE versions the parent window does not have
// access to document.body in new blank window.
var navigatedUrl;
var mockWin = {open: function(url) { navigatedUrl = url; }};
// Test string determines that all necessary escaping transformations happen,
// and that they happen in the right order (HTML->JS->URI).
// - " which would be escaped by HTML escaping and JS string escaping. It
// should be HTML escaped.
// - \ which would be escaped by JS string escaping and percent-encoded
// by encodeURI(). It gets JS string escaped first (to two '\') and then
// percent-encoded.
var win = goog.window.openBlank('"\\', {}, mockWin);
assertEquals('javascript:""%5C%5C"', navigatedUrl);
}
function testOpenIosBlank() {
if (!goog.labs.userAgent.engine.isWebKit() || !window.navigator) {
// Don't even try this on IE8!
return;
}
var attrs = {};
var dispatchedEvent = null;
var element = {
setAttribute: function(name, value) { attrs[name] = value; },
dispatchEvent: function(event) { dispatchedEvent = event; }
};
stubs.replace(window.document, 'createElement', function(name) {
if (name == goog.dom.TagName.A) {
return element;
}
return null;
});
stubs.set(window.navigator, 'standalone', true);
stubs.replace(goog.labs.userAgent.platform, 'isIos', goog.functions.TRUE);
var newWin = goog.window.open('http://google.com', {target: '_blank'});
// This mode cannot return a new window.
assertNotNull(newWin);
assertUndefined(newWin.document);
// Attributes.
// element.href is directly set through goog.dom.safe.setAnchorHref, not with
// element.setAttribute.
assertEquals('http://google.com', element.href);
assertEquals('_blank', attrs['target']);
assertEquals('', attrs['rel'] || '');
// Click event.
assertNotNull(dispatchedEvent);
assertEquals('click', dispatchedEvent.type);
}
function testOpenIosBlankNoreferrer() {
if (!goog.labs.userAgent.engine.isWebKit() || !window.navigator) {
// Don't even try this on IE8!
return;
}
var attrs = {};
var dispatchedEvent = null;
var element = {
setAttribute: function(name, value) { attrs[name] = value; },
dispatchEvent: function(event) { dispatchedEvent = event; }
};
stubs.replace(window.document, 'createElement', function(name) {
if (name == goog.dom.TagName.A) {
return element;
}
return null;
});
stubs.set(window.navigator, 'standalone', true);
stubs.replace(goog.labs.userAgent.platform, 'isIos', goog.functions.TRUE);
var newWin = goog.window.open(
'http://google.com', {target: '_blank', noreferrer: true});
// This mode cannot return a new window.
assertNotNull(newWin);
assertUndefined(newWin.document);
// Attributes.
// element.href is directly set through goog.dom.safe.setAnchorHref, not with
// element.setAttribute.
assertEquals('http://google.com', element.href);
assertEquals('_blank', attrs['target']);
assertEquals('noreferrer', attrs['rel']);
// Click event.
assertNotNull(dispatchedEvent);
assertEquals('click', dispatchedEvent.type);
}
function testOpenNoReferrerEscapesUrl() {
var documentWriteHtml;
var mockNewWin = {};
mockNewWin.document = {
write: function(html) { documentWriteHtml = html; },
close: function() {}
};
var mockWin = {open: function() { return mockNewWin; }};
goog.window.open('https://hello&world', {noreferrer: true}, mockWin);
assertRegExp(
'Does not contain expected HTML-escaped string: ' + documentWriteHtml,
/hello&world/, documentWriteHtml);
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy