UNPKG

accessibility-developer-tools

Version:

This is a library of accessibility-related testing and utility code.

571 lines (484 loc) 20.1 kB
// Copyright 2013 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. /** * @fileoverview Unit tests for goog.dom.safe. * @suppress {accessControls} Private methods are accessed for test purposes. */ goog.provide('goog.dom.safeTest'); goog.setTestOnly('goog.dom.safeTest'); goog.require('goog.dom.safe'); goog.require('goog.dom.safe.InsertAdjacentHtmlPosition'); goog.require('goog.html.SafeHtml'); goog.require('goog.html.SafeStyle'); goog.require('goog.html.SafeUrl'); goog.require('goog.html.TrustedResourceUrl'); goog.require('goog.html.testing'); goog.require('goog.string'); goog.require('goog.string.Const'); goog.require('goog.testing'); goog.require('goog.testing.StrictMock'); goog.require('goog.testing.jsunit'); goog.require('goog.userAgent'); var mockWindowOpen; function tearDown() { if (mockWindowOpen) { mockWindowOpen.$tearDown(); } } function testInsertAdjacentHtml() { var writtenHtml; var writtenPosition; var mockNode = /** @type {!Node} */ ({ 'insertAdjacentHTML': function(position, html) { writtenPosition = position; writtenHtml = html; } }); goog.dom.safe.insertAdjacentHtml( mockNode, goog.dom.safe.InsertAdjacentHtmlPosition.BEFOREBEGIN, goog.html.SafeHtml.create('div', {}, 'foobar')); assertEquals('<div>foobar</div>', writtenHtml); assertEquals('beforebegin', writtenPosition); } function testSetInnerHtml() { var mockElement = /** @type {!Element} */ ({'tagName': 'DIV', 'innerHTML': 'blarg'}); var html = '<script>somethingTrusted();<' + '/script>'; var safeHtml = goog.html.testing.newSafeHtmlForTest(html); goog.dom.safe.setInnerHtml(mockElement, safeHtml); assertEquals(html, mockElement.innerHTML); } function testSetInnerHtml_doesntAllowScript() { var script = /** @type {!Element} */ ({'tagName': 'SCRIPT', 'innerHTML': 'blarg'}); var safeHtml = goog.html.SafeHtml.htmlEscape('alert(1);'); assertThrows(function() { goog.dom.safe.setInnerHtml(script, safeHtml); }); } function testSetInnerHtml_doesntAllowStyle() { var style = /** @type {!Element} */ ({'tagName': 'STYLE', 'innerHTML': 'blarg'}); var safeHtml = goog.html.SafeHtml.htmlEscape('A { color: red; }'); assertThrows(function() { goog.dom.safe.setInnerHtml(style, safeHtml); }); } function testSetStyle() { var style = goog.html.SafeStyle.fromConstant(goog.string.Const.from('color: red;')); var elem = document.createElement('div'); assertEquals('', elem.style.color); // sanity check goog.dom.safe.setStyle(elem, style); assertEquals('red', elem.style.color); } function testDocumentWrite() { var mockDoc = /** @type {!Document} */ ({ 'html': null, /** @suppress {globalThis} */ 'write': function(html) { this['html'] = html; } }); var html = '<script>somethingTrusted();<' + '/script>'; var safeHtml = goog.html.testing.newSafeHtmlForTest(html); goog.dom.safe.documentWrite(mockDoc, safeHtml); assertEquals(html, mockDoc.html); } function testsetLinkHrefAndRel_trustedResourceUrl() { var mockLink = /** @type {!HTMLLinkElement} */ ({'href': null, 'rel': null}); var url = goog.html.TrustedResourceUrl.fromConstant( goog.string.Const.from('javascript:trusted();')); // Test case-insensitive too. goog.dom.safe.setLinkHrefAndRel(mockLink, url, 'foo, Stylesheet, bar'); assertEquals('javascript:trusted();', mockLink.href); goog.dom.safe.setLinkHrefAndRel(mockLink, url, 'foo, bar'); assertEquals('javascript:trusted();', mockLink.href); } function testsetLinkHrefAndRel_safeUrl() { var mockLink = /** @type {!HTMLLinkElement} */ ({'href': null, 'rel': null}); var url = goog.html.SafeUrl.fromConstant( goog.string.Const.from('javascript:trusted();')); assertThrows(function() { goog.dom.safe.setLinkHrefAndRel(mockLink, url, 'foo, stylesheet, bar'); }); goog.dom.safe.setLinkHrefAndRel(mockLink, url, 'foo, bar'); assertEquals('javascript:trusted();', mockLink.href); } function testsetLinkHrefAndRel_string() { var mockLink = /** @type {!HTMLLinkElement} */ ({'href': null, 'rel': null}); assertThrows(function() { goog.dom.safe.setLinkHrefAndRel( mockLink, 'javascript:evil();', 'foo, stylesheet, bar'); }); goog.dom.safe.setLinkHrefAndRel(mockLink, 'javascript:evil();', 'foo, bar'); assertEquals('about:invalid#zClosurez', mockLink.href); } function testsetLinkHrefAndRel_assertsType() { if (!goog.userAgent.IE || goog.userAgent.isVersionOrHigher(10)) { var otherElement = document.createElement('A'); var ex = assertThrows(function() { goog.dom.safe.setLinkHrefAndRel( /** @type {!HTMLLinkElement} */ (otherElement), 'http://example.com/', 'author'); }); assert( goog.string.contains(ex.message, 'Argument is not a HTMLLinkElement')); } } /** * Returns a link element, incorrectly typed as a Location. * @return {!Location} * @suppress {checkTypes} */ function makeLinkElementTypedAsLocation() { return document.createElement('LINK'); } function testSetLocationHref() { var mockLoc = /** @type {!Location} */ ({'href': 'blarg'}); goog.dom.safe.setLocationHref(mockLoc, 'javascript:evil();'); assertEquals('about:invalid#zClosurez', mockLoc.href); mockLoc = /** @type {!Location} */ ({'href': 'blarg'}); var safeUrl = goog.html.SafeUrl.fromConstant( goog.string.Const.from('javascript:trusted();')); goog.dom.safe.setLocationHref(mockLoc, safeUrl); assertEquals('javascript:trusted();', mockLoc.href); // Asserts correct runtime type. if (!goog.userAgent.IE || goog.userAgent.isVersionOrHigher(10)) { var ex = assertThrows(function() { goog.dom.safe.setLocationHref(makeLinkElementTypedAsLocation(), safeUrl); }); assert(goog.string.contains(ex.message, 'Argument is not a Location')); } } function testSetAnchorHref() { var anchor = /** @type {!HTMLAnchorElement} */ (document.createElement('A')); goog.dom.safe.setAnchorHref(anchor, 'javascript:evil();'); assertEquals('about:invalid#zClosurez', anchor.href); anchor = /** @type {!HTMLAnchorElement} */ (document.createElement('A')); var safeUrl = goog.html.SafeUrl.fromConstant( goog.string.Const.from('javascript:trusted();')); goog.dom.safe.setAnchorHref(anchor, safeUrl); assertEquals('javascript:trusted();', anchor.href); // Works with mocks too. var mockAnchor = /** @type {!HTMLAnchorElement} */ ({'href': 'blarg'}); goog.dom.safe.setAnchorHref(mockAnchor, 'javascript:evil();'); assertEquals('about:invalid#zClosurez', mockAnchor.href); mockAnchor = /** @type {!HTMLAnchorElement} */ ({'href': 'blarg'}); safeUrl = goog.html.SafeUrl.fromConstant( goog.string.Const.from('javascript:trusted();')); goog.dom.safe.setAnchorHref(mockAnchor, safeUrl); assertEquals('javascript:trusted();', mockAnchor.href); // Asserts correct runtime type. if (!goog.userAgent.IE || goog.userAgent.isVersionOrHigher(10)) { var otherElement = document.createElement('LINK'); var ex = assertThrows(function() { goog.dom.safe.setAnchorHref( /** @type {!HTMLAnchorElement} */ (otherElement), safeUrl); }); assert(goog.string.contains( ex.message, 'Argument is not a HTMLAnchorElement')); } } function testSetImageSrc_withSafeUrlObject() { var mockImageElement = /** @type {!HTMLImageElement} */ ({'src': 'blarg'}); goog.dom.safe.setImageSrc(mockImageElement, 'javascript:evil();'); assertEquals('about:invalid#zClosurez', mockImageElement.src); mockImageElement = /** @type {!HTMLImageElement} */ ({'src': 'blarg'}); var safeUrl = goog.html.SafeUrl.fromConstant( goog.string.Const.from('javascript:trusted();')); goog.dom.safe.setImageSrc(mockImageElement, safeUrl); assertEquals('javascript:trusted();', mockImageElement.src); // Asserts correct runtime type. if (!goog.userAgent.IE || goog.userAgent.isVersionOrHigher(10)) { var otherElement = document.createElement('SCRIPT'); var ex = assertThrows(function() { goog.dom.safe.setImageSrc( /** @type {!HTMLImageElement} */ (otherElement), safeUrl); }); assert( goog.string.contains(ex.message, 'Argument is not a HTMLImageElement')); } } function testSetImageSrc_withHttpsUrl() { var mockImageElement = /** @type {!HTMLImageElement} */ ({'src': 'blarg'}); var safeUrl = 'https://trusted_url'; goog.dom.safe.setImageSrc(mockImageElement, safeUrl); assertEquals(safeUrl, mockImageElement.src); } function testSetEmbedSrc() { var url = goog.html.TrustedResourceUrl.fromConstant( goog.string.Const.from('javascript:trusted();')); var mockElement = /** @type {!HTMLEmbedElement} */ ({'src': 'blarg'}); goog.dom.safe.setEmbedSrc(mockElement, url); assertEquals('javascript:trusted();', mockElement.src); // Asserts correct runtime type. if (!goog.userAgent.IE || goog.userAgent.isVersionOrHigher(10)) { var otherElement = document.createElement('IMAGE'); var ex = assertThrows(function() { goog.dom.safe.setEmbedSrc( /** @type {!HTMLEmbedElement} */ (otherElement), url); }); assert( goog.string.contains(ex.message, 'Argument is not a HTMLEmbedElement')); } } function testSetFrameSrc() { var url = goog.html.TrustedResourceUrl.fromConstant( goog.string.Const.from('javascript:trusted();')); var mockElement = /** @type {!HTMLFrameElement} */ ({'src': 'blarg'}); goog.dom.safe.setFrameSrc(mockElement, url); assertEquals('javascript:trusted();', mockElement.src); // Asserts correct runtime type. if (!goog.userAgent.IE || goog.userAgent.isVersionOrHigher(10)) { var otherElement = document.createElement('IMAGE'); var ex = assertThrows(function() { goog.dom.safe.setFrameSrc( /** @type {!HTMLFrameElement} */ (otherElement), url); }); assert( goog.string.contains(ex.message, 'Argument is not a HTMLFrameElement')); } } function testSetIframeSrc() { var url = goog.html.TrustedResourceUrl.fromConstant( goog.string.Const.from('javascript:trusted();')); var mockElement = /** @type {!HTMLIFrameElement} */ ({'src': 'blarg'}); goog.dom.safe.setIframeSrc(mockElement, url); assertEquals('javascript:trusted();', mockElement.src); // Asserts correct runtime type. if (!goog.userAgent.IE || goog.userAgent.isVersionOrHigher(10)) { var otherElement = document.createElement('IMAGE'); var ex = assertThrows(function() { goog.dom.safe.setIframeSrc( /** @type {!HTMLIFrameElement} */ (otherElement), url); }); assert(goog.string.contains( ex.message, 'Argument is not a HTMLIFrameElement')); } } function testSetIframeSrcdoc() { var html = goog.html.SafeHtml.create('div', {}, 'foobar'); var mockIframe = /** @type {!HTMLIFrameElement} */ ({'srcdoc': ''}); goog.dom.safe.setIframeSrcdoc(mockIframe, html); assertEquals('<div>foobar</div>', mockIframe.srcdoc); // Asserts correct runtime type. if (!goog.userAgent.IE || goog.userAgent.isVersionOrHigher(10)) { var otherElement = document.createElement('IMAGE'); var ex = assertThrows(function() { goog.dom.safe.setIframeSrcdoc( /** @type {!HTMLIFrameElement} */ (otherElement), html); }); assert(goog.string.contains( ex.message, 'Argument is not a HTMLIFrameElement')); } } function testSetObjectData() { var url = goog.html.TrustedResourceUrl.fromConstant( goog.string.Const.from('javascript:trusted();')); var mockElement = /** @type {!HTMLObjectElement} */ ({'data': 'blarg'}); goog.dom.safe.setObjectData(mockElement, url); assertEquals('javascript:trusted();', mockElement.data); // Asserts correct runtime type. if (!goog.userAgent.IE || goog.userAgent.isVersionOrHigher(10)) { var otherElement = document.createElement('IMAGE'); var ex = assertThrows(function() { goog.dom.safe.setObjectData( /** @type {!HTMLObjectElement} */ (otherElement), url); }); assert(goog.string.contains( ex.message, 'Argument is not a HTMLObjectElement')); } } function testSetScriptSrc() { var url = goog.html.TrustedResourceUrl.fromConstant( goog.string.Const.from('javascript:trusted();')); var mockElement = /** @type {!HTMLScriptElement} */ ({'src': 'blarg'}); goog.dom.safe.setScriptSrc(mockElement, url); assertEquals('javascript:trusted();', mockElement.src); // Asserts correct runtime type. if (!goog.userAgent.IE || goog.userAgent.isVersionOrHigher(10)) { var otherElement = document.createElement('IMAGE'); var ex = assertThrows(function() { goog.dom.safe.setScriptSrc( /** @type {!HTMLScriptElement} */ (otherElement), url); }); assert(goog.string.contains( ex.message, 'Argument is not a HTMLScriptElement')); } } function testOpenInWindow() { mockWindowOpen = /** @type {?} */ (goog.testing.createMethodMock(window, 'open')); var fakeWindow = {}; mockWindowOpen('about:invalid#zClosurez', 'name', 'specs', true) .$returns(fakeWindow); mockWindowOpen.$replay(); var retVal = goog.dom.safe.openInWindow( 'javascript:evil();', window, goog.string.Const.from('name'), 'specs', true); mockWindowOpen.$verify(); assertEquals( 'openInWindow should return the created window', fakeWindow, retVal); mockWindowOpen.$reset(); retVal = null; var safeUrl = goog.html.SafeUrl.fromConstant( goog.string.Const.from('javascript:trusted();')); mockWindowOpen('javascript:trusted();', 'name', 'specs', true) .$returns(fakeWindow); mockWindowOpen.$replay(); retVal = goog.dom.safe.openInWindow( safeUrl, window, goog.string.Const.from('name'), 'specs', true); mockWindowOpen.$verify(); assertEquals( 'openInWindow should return the created window', fakeWindow, retVal); } function testAssertIsLocation() { assertNotThrows(function() { goog.dom.safe.assertIsLocation_(window.location); }); // Ad-hoc mock objects are allowed. var o = {foo: 'bar'}; assertNotThrows(function() { goog.dom.safe.assertIsLocation_(o); }); // So are fancy mocks. var mock = new goog.testing.StrictMock(window.location); assertNotThrows(function() { goog.dom.safe.assertIsLocation_(mock); }); if (!goog.userAgent.IE || goog.userAgent.isVersionOrHigher(10)) { var linkElement = document.createElement('LINK'); var ex = assertThrows(function() { goog.dom.safe.assertIsLocation_(linkElement); }); assert(goog.string.contains(ex.message, 'Argument is not a Location')); } } function testAssertIsHtmlAnchorElement() { var anchorElement = document.createElement('A'); assertNotThrows(function() { goog.dom.safe.assertIsHTMLAnchorElement_(anchorElement); }); // Ad-hoc mock objects are allowed. var o = {foo: 'bar'}; assertNotThrows(function() { goog.dom.safe.assertIsHTMLAnchorElement_(o); }); // So are fancy mocks. var mock = new goog.testing.StrictMock(anchorElement); assertNotThrows(function() { goog.dom.safe.assertIsHTMLAnchorElement_(mock); }); if (!goog.userAgent.IE || goog.userAgent.isVersionOrHigher(10)) { var otherElement = document.createElement('LINK'); var ex = assertThrows(function() { goog.dom.safe.assertIsHTMLAnchorElement_(otherElement); }); assert(goog.string.contains( ex.message, 'Argument is not a HTMLAnchorElement')); } } function testAssertIsHtmlLinkElement() { var linkElement = document.createElement('LINK'); assertNotThrows(function() { goog.dom.safe.assertIsHTMLLinkElement_(linkElement); }); // Ad-hoc mock objects are allowed. var o = {foo: 'bar'}; assertNotThrows(function() { goog.dom.safe.assertIsHTMLLinkElement_(o); }); // So are fancy mocks. var mock = new goog.testing.StrictMock(linkElement); assertNotThrows(function() { goog.dom.safe.assertIsHTMLLinkElement_(mock); }); if (!goog.userAgent.IE || goog.userAgent.isVersionOrHigher(10)) { var otherElement = document.createElement('A'); var ex = assertThrows(function() { goog.dom.safe.assertIsHTMLLinkElement_(otherElement); }); assert( goog.string.contains(ex.message, 'Argument is not a HTMLLinkElement')); } } function testAssertIsHtmlImageElement() { var imgElement = document.createElement('IMG'); assertNotThrows(function() { goog.dom.safe.assertIsHTMLImageElement_(imgElement); }); // Ad-hoc mock objects are allowed. var o = {foo: 'bar'}; assertNotThrows(function() { goog.dom.safe.assertIsHTMLImageElement_(o); }); // So are fancy mocks. var mock = new goog.testing.StrictMock(imgElement); assertNotThrows(function() { goog.dom.safe.assertIsHTMLImageElement_(mock); }); if (!goog.userAgent.IE || goog.userAgent.isVersionOrHigher(10)) { var otherElement = document.createElement('SCRIPT'); var ex = assertThrows(function() { goog.dom.safe.assertIsHTMLImageElement_(otherElement); }); assert( goog.string.contains(ex.message, 'Argument is not a HTMLImageElement')); } } function testAssertIsHtmlEmbedElement() { var el = document.createElement('EMBED'); assertNotThrows(function() { goog.dom.safe.assertIsHTMLEmbedElement_(el); }); if (!goog.userAgent.IE || goog.userAgent.isVersionOrHigher(10)) { var otherElement = document.createElement('SCRIPT'); var ex = assertThrows(function() { goog.dom.safe.assertIsHTMLEmbedElement_(otherElement); }); assert( goog.string.contains(ex.message, 'Argument is not a HTMLEmbedElement')); } } function testAssertIsHtmlFrameElement() { var el = document.createElement('FRAME'); assertNotThrows(function() { goog.dom.safe.assertIsHTMLFrameElement_(el); }); if (!goog.userAgent.IE || goog.userAgent.isVersionOrHigher(10)) { var otherElement = document.createElement('SCRIPT'); var ex = assertThrows(function() { goog.dom.safe.assertIsHTMLFrameElement_(otherElement); }); assert( goog.string.contains(ex.message, 'Argument is not a HTMLFrameElement')); } } function testAssertIsHtmlIFrameElement() { var el = document.createElement('IFRAME'); assertNotThrows(function() { goog.dom.safe.assertIsHTMLIFrameElement_(el); }); if (!goog.userAgent.IE || goog.userAgent.isVersionOrHigher(10)) { var otherElement = document.createElement('SCRIPT'); var ex = assertThrows(function() { goog.dom.safe.assertIsHTMLIFrameElement_(otherElement); }); assert(goog.string.contains( ex.message, 'Argument is not a HTMLIFrameElement')); } } function testAssertIsHtmlObjectElement() { var el = document.createElement('OBJECT'); assertNotThrows(function() { goog.dom.safe.assertIsHTMLObjectElement_(el); }); if (!goog.userAgent.IE || goog.userAgent.isVersionOrHigher(10)) { var otherElement = document.createElement('SCRIPT'); var ex = assertThrows(function() { goog.dom.safe.assertIsHTMLObjectElement_(otherElement); }); assert(goog.string.contains( ex.message, 'Argument is not a HTMLObjectElement')); } } function testAssertIsHtmlScriptElement() { var el = document.createElement('SCRIPT'); assertNotThrows(function() { goog.dom.safe.assertIsHTMLScriptElement_(el); }); if (!goog.userAgent.IE || goog.userAgent.isVersionOrHigher(10)) { var otherElement = document.createElement('IMG'); var ex = assertThrows(function() { goog.dom.safe.assertIsHTMLScriptElement_(otherElement); }); assert(goog.string.contains( ex.message, 'Argument is not a HTMLScriptElement')); } }