| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <meta http-equiv="Expire" content="0"/> | |
| <meta charset="utf-8"> | |
| <title>click_link_test.html</title> | |
| <link rel="stylesheet" href="/filez/_main/third_party/js/qunit/qunit.css"> | |
| <script src="/filez/_main/third_party/js/qunit/qunit.js"></script> | |
| <script src="/filez/_main/third_party/js/qunit/qunit_test_runner.js"></script> | |
| <script src="test_bootstrap.js"></script> | |
| <script type="text/javascript"> | |
| goog.require('bot.action'); | |
| goog.require('bot.locators'); | |
| goog.require('bot.userAgent'); | |
| goog.require('goog.Promise'); | |
| goog.require('goog.Uri'); | |
| goog.require('goog.debug.DivConsole'); | |
| goog.require('goog.log'); | |
| goog.require('goog.dom'); | |
| goog.require('goog.events'); | |
| goog.require('goog.events.EventType'); | |
| goog.require('goog.math.Coordinate'); | |
| goog.require('goog.style'); | |
| goog.require('goog.userAgent'); | |
| goog.require('goog.userAgent.product'); | |
| </script> | |
| <script type="text/javascript"> | |
| var divConsole; | |
| var iframe, iframeWindow, other, otherWindow; | |
| var link, link2; | |
| var findElement = bot.locators.findElement; | |
| var findElements = bot.locators.findElements; | |
| var log = goog.log.getLogger('click_link_test'); | |
| QUnit.testStart(function() { | |
| iframe = bot.locators.findElement({id: 'iframe'}); | |
| iframeWindow = goog.dom.getFrameContentWindow(iframe); | |
| otherFrame = bot.locators.findElement({id: 'other'}); | |
| otherFrameWindow = goog.dom.getFrameContentWindow(otherFrame); | |
| iframeWindow.location = resolveUrl('testdata/click_iframe.html'); | |
| link = bot.locators.findElement({id: 'link'}); | |
| link2 = bot.locators.findElement({id: 'link2'}); | |
| goog.events.removeAll(link); | |
| goog.events.removeAll(link2); | |
| link.blur(); | |
| link2.blur(); | |
| window.focus(); | |
| }); | |
| function checkActionCompatibility(action) { | |
| if (action == bot.action.tap) { | |
| return bot.events.SUPPORTS_TOUCH_EVENTS; | |
| } | |
| return true; | |
| } | |
| function waitForLoad(iframe) { | |
| return new goog.Promise(function(done) { | |
| goog.events.listenOnce(iframe, 'load', done); | |
| }); | |
| } | |
| function timeout() { | |
| return new goog.Promise(function(done) { | |
| setTimeout(done, 0); | |
| }); | |
| } | |
| function resolveUrl(url) { | |
| return goog.Uri.resolve(window.location.href, url).toString(); | |
| } | |
| function getClickTarget(url) { | |
| var doc = goog.dom.getFrameContentDocument(iframe); | |
| var target = bot.locators.findElement({'id': 'iframeClickTarget'}, doc); | |
| target.href = resolveUrl(url); | |
| return target; | |
| } | |
| function executesDefaultHandler(assert, action) { | |
| if (!checkActionCompatibility(action)) { | |
| assert.ok(true, 'Action not supported, skipping'); | |
| return; | |
| } | |
| var clickTarget = findElement({id: 'clickTarget'}); | |
| goog.events.removeAll(clickTarget); | |
| var targetHref = '#' + Math.random(); | |
| clickTarget.href = targetHref; | |
| action(clickTarget); | |
| var done = assert.async(); | |
| timeout().then(function() { | |
| assert.strictEqual(window.location.hash, targetHref); | |
| done(); | |
| }); | |
| } | |
| QUnit.test('click executes default handler', function(assert) { | |
| executesDefaultHandler(assert, bot.action.click); | |
| }); | |
| QUnit.test('tap executes default handler', function(assert) { | |
| executesDefaultHandler(assert, bot.action.tap); | |
| }); | |
| function nestedElementExecutesDefaultHandler(assert, action) { | |
| if (!checkActionCompatibility(action)) { | |
| assert.ok(true, 'Action not supported, skipping'); | |
| return; | |
| } | |
| var parent = findElement({id: 'clickTargetWithAChild'}); | |
| var targetHref = '#' + Math.random(); | |
| parent.href = targetHref; | |
| var clickTarget = goog.dom.getFirstElementChild(parent); | |
| action(clickTarget); | |
| var done = assert.async(); | |
| timeout().then(function() { | |
| assert.strictEqual(window.location.hash, targetHref); | |
| done(); | |
| }); | |
| } | |
| QUnit.test('click nested element executes default handler', function(assert) { | |
| nestedElementExecutesDefaultHandler(assert, bot.action.click); | |
| }); | |
| QUnit.test('tap nested element executes default handler', function(assert) { | |
| nestedElementExecutesDefaultHandler(assert, bot.action.tap); | |
| }); | |
| function correctlyResolvesEmptyFragment(assert, action) { | |
| if (!checkActionCompatibility(action)) { | |
| assert.ok(true, 'Action not supported, skipping'); | |
| return; | |
| } | |
| var clickTarget = findElement({id: 'clickTarget'}); | |
| goog.events.removeAll(clickTarget); | |
| clickTarget.href = '#'; | |
| action(clickTarget); | |
| var done = assert.async(); | |
| timeout().then(function() { | |
| var windowHref = window.location.href; | |
| assert.strictEqual(windowHref.charAt(windowHref.length - 1), '#'); | |
| done(); | |
| }); | |
| } | |
| QUnit.test('click correctly resolves empty fragment', function(assert) { | |
| correctlyResolvesEmptyFragment(assert, bot.action.click); | |
| }); | |
| QUnit.test('tap correctly resolves empty fragment', function(assert) { | |
| correctlyResolvesEmptyFragment(assert, bot.action.tap); | |
| }); | |
| function absoluteUrlInAnIframeExecutesDefaultHandler(assert, action) { | |
| if (!checkActionCompatibility(action)) { | |
| assert.ok(true, 'Action not supported, skipping'); | |
| return; | |
| } | |
| var done = assert.async(); | |
| waitForLoad(iframe).then(function() { | |
| var domHelper = goog.dom.getDomHelper(iframeWindow); | |
| var clickTarget = domHelper.getElement('iframeClickTarget'); | |
| var targetHref = goog.Uri.resolve(iframeWindow.location, | |
| '#' + Math.random()).toString(); | |
| assert.ok(targetHref.indexOf('http') !== -1); | |
| clickTarget.href = targetHref; | |
| action(clickTarget); | |
| timeout().then(function() { | |
| assert.strictEqual(iframeWindow.location.href, targetHref); | |
| done(); | |
| }); | |
| }); | |
| } | |
| QUnit.test('click absolute url in an iframe executes default handler', function(assert) { | |
| absoluteUrlInAnIframeExecutesDefaultHandler(assert, bot.action.click); | |
| }); | |
| QUnit.test('tap absolute url in an iframe executes default handler', function(assert) { | |
| absoluteUrlInAnIframeExecutesDefaultHandler(assert, bot.action.tap); | |
| }); | |
| function absoluteServerPathAnchorInAnIframeExecutesDefaultHandler(assert, action) { | |
| if (!checkActionCompatibility(action)) { | |
| assert.ok(true, 'Action not supported, skipping'); | |
| return; | |
| } | |
| var done = assert.async(); | |
| waitForLoad(iframe).then(function() { | |
| var domHelper = goog.dom.getDomHelper(iframeWindow); | |
| var clickTarget = domHelper.getElement('iframeClickTarget'); | |
| var testPath = window.location.pathname; | |
| var targetHref = testPath.substring(0, testPath.lastIndexOf('/')) + | |
| '/testdata/click_iframe.html#' + Math.random(); | |
| clickTarget.href = targetHref; | |
| action(clickTarget); | |
| timeout().then(function() { | |
| assert.ok(iframeWindow.location.href.indexOf(targetHref) !== -1); | |
| done(); | |
| }); | |
| }); | |
| } | |
| QUnit.test('click absolute server path anchor in an iframe executes default handler', function(assert) { | |
| absoluteServerPathAnchorInAnIframeExecutesDefaultHandler(assert, bot.action.click); | |
| }); | |
| QUnit.test('tap absolute server path anchor in an iframe executes default handler', function(assert) { | |
| absoluteServerPathAnchorInAnIframeExecutesDefaultHandler(assert, bot.action.tap); | |
| }); | |
| function relativeServerPathAnchorInAnIframeExecutesDefaultHandler(assert, action) { | |
| if (!checkActionCompatibility(action)) { | |
| assert.ok(true, 'Action not supported, skipping'); | |
| return; | |
| } | |
| var done = assert.async(); | |
| waitForLoad(iframe).then(function() { | |
| var domHelper = goog.dom.getDomHelper(iframeWindow); | |
| var clickTarget = domHelper.getElement('iframeClickTarget'); | |
| var targetHref = 'click_iframe.html#' + Math.random(); | |
| clickTarget.href = targetHref; | |
| action(clickTarget); | |
| timeout().then(function() { | |
| assert.ok(iframeWindow.location.href.indexOf(targetHref) !== -1); | |
| done(); | |
| }); | |
| }); | |
| } | |
| QUnit.test('click relative server path anchor in an iframe executes default handler', function(assert) { | |
| relativeServerPathAnchorInAnIframeExecutesDefaultHandler(assert, bot.action.click); | |
| }); | |
| QUnit.test('tap relative server path anchor in an iframe executes default handler', function(assert) { | |
| relativeServerPathAnchorInAnIframeExecutesDefaultHandler(assert, bot.action.tap); | |
| }); | |
| function hashOnlyAnchorInAnIframeExecutesDefaultHandler(assert, action) { | |
| if (!checkActionCompatibility(action)) { | |
| assert.ok(true, 'Action not supported, skipping'); | |
| return; | |
| } | |
| var done = assert.async(); | |
| waitForLoad(iframe).then(function() { | |
| var domHelper = goog.dom.getDomHelper(iframeWindow); | |
| var clickTarget = domHelper.getElement('iframeClickTarget'); | |
| var targetHref = '#' + Math.random(); | |
| clickTarget.href = targetHref; | |
| action(clickTarget); | |
| timeout().then(function() { | |
| assert.strictEqual(iframeWindow.location.hash, targetHref); | |
| done(); | |
| }); | |
| }); | |
| } | |
| QUnit.test('click hash only anchor in an iframe executes default handler', function(assert) { | |
| hashOnlyAnchorInAnIframeExecutesDefaultHandler(assert, bot.action.click); | |
| }); | |
| QUnit.test('tap hash only anchor in an iframe executes default handler', function(assert) { | |
| hashOnlyAnchorInAnIframeExecutesDefaultHandler(assert, bot.action.tap); | |
| }); | |
| function nestedElementInAnIframeExecutesDefaultHandler(assert, action) { | |
| if (!checkActionCompatibility(action)) { | |
| assert.ok(true, 'Action not supported, skipping'); | |
| return; | |
| } | |
| var done = assert.async(); | |
| waitForLoad(iframe).then(function() { | |
| var domHelper = goog.dom.getDomHelper(iframeWindow); | |
| var parent = domHelper.getElement('iframeClickTargetWithAChild'); | |
| var clickTarget = goog.dom.getFirstElementChild(parent); | |
| var targetHref = '#' + Math.random(); | |
| parent.href = targetHref; | |
| action(clickTarget); | |
| timeout().then(function() { | |
| assert.strictEqual(iframeWindow.location.hash, targetHref); | |
| done(); | |
| }); | |
| }); | |
| } | |
| QUnit.test('click nested element in an iframe executes default handler', function(assert) { | |
| nestedElementInAnIframeExecutesDefaultHandler(assert, bot.action.click); | |
| }); | |
| QUnit.test('tap hash nested element in an iframe executes default handler', function(assert) { | |
| nestedElementInAnIframeExecutesDefaultHandler(assert, bot.action.tap); | |
| }); | |
| function doesNotFollowLinkWhenEventDefaultPrevented(assert, action) { | |
| if (!checkActionCompatibility(action)) { | |
| assert.ok(true, 'Action not supported, skipping'); | |
| return; | |
| } | |
| var clickTarget = findElement({id: 'clickTarget'}); | |
| goog.events.removeAll(clickTarget); | |
| var previousLocation = window.location.href; | |
| clickTarget.href = '#' + Math.random(); | |
| goog.events.listen(clickTarget, goog.events.EventType.CLICK, function(e) { | |
| e.preventDefault(); | |
| }); | |
| action(clickTarget); | |
| var done = assert.async(); | |
| timeout().then(function() { | |
| assert.strictEqual(window.location.href, previousLocation); | |
| done(); | |
| }); | |
| } | |
| QUnit.test('click does not follow link when event default prevented', function(assert) { | |
| doesNotFollowLinkWhenEventDefaultPrevented(assert, bot.action.click); | |
| }); | |
| QUnit.test('tap does not follow link when event default prevented', function(assert) { | |
| doesNotFollowLinkWhenEventDefaultPrevented(assert, bot.action.tap); | |
| }); | |
| function doNotFollowLinkWhenEventDefaultPreventedWithInlineHandler(assert, action) { | |
| if (!checkActionCompatibility(action)) { | |
| assert.ok(true, 'Action not supported, skipping'); | |
| return; | |
| } | |
| var clickTarget = findElement({id: 'clickTargetWithInlineHandler'}); | |
| var previousLocation = window.location.href; | |
| clickTarget.href = '#' + Math.random(); | |
| action(clickTarget); | |
| var done = assert.async(); | |
| timeout().then(function() { | |
| assert.strictEqual(window.location.href, previousLocation); | |
| done(); | |
| }); | |
| } | |
| QUnit.test('click do not follow link when event default prevented with inline handler', function(assert) { | |
| doNotFollowLinkWhenEventDefaultPreventedWithInlineHandler(assert, bot.action.click); | |
| }); | |
| QUnit.test('tap do not follow link when event default prevented with inline handler', function(assert) { | |
| doNotFollowLinkWhenEventDefaultPreventedWithInlineHandler(assert, bot.action.tap); | |
| }); | |
| function doesNotFollowLinkWhenNoHrefIsGiven(assert, action) { | |
| if (!checkActionCompatibility(action)) { | |
| assert.ok(true, 'Action not supported, skipping'); | |
| return; | |
| } | |
| var clickTarget = findElement({id: 'clickTargetWithNoHref'}); | |
| goog.events.removeAll(clickTarget); | |
| var previousLocation = window.location.href; | |
| action(clickTarget); | |
| var done = assert.async(); | |
| timeout().then(function() { | |
| assert.strictEqual(window.location.href, previousLocation); | |
| done(); | |
| }); | |
| } | |
| QUnit.test('click does not follow link when no href is given', function(assert) { | |
| doesNotFollowLinkWhenNoHrefIsGiven(assert, bot.action.click); | |
| }); | |
| QUnit.test('tap does not follow link when no href is given', function(assert) { | |
| doesNotFollowLinkWhenNoHrefIsGiven(assert, bot.action.tap); | |
| }); | |
| function nestedElelementDoesNotFollowLinkWhenNoHrefIsGiven(assert, action) { | |
| if (!checkActionCompatibility(action)) { | |
| assert.ok(true, 'Action not supported, skipping'); | |
| return; | |
| } | |
| var clickTarget = findElement({id: 'clickTargetWithAChildAndNoHref'}); | |
| var previousLocation = window.location.href; | |
| action(clickTarget); | |
| assert.ok(window.location.href.indexOf(previousLocation) !== -1); | |
| } | |
| QUnit.test('click nested elelment does not follow link when no href is given', function(assert) { | |
| nestedElelementDoesNotFollowLinkWhenNoHrefIsGiven(assert, bot.action.click); | |
| }); | |
| QUnit.test('tap nested elelment does not follow link when no href is given', function(assert) { | |
| nestedElelementDoesNotFollowLinkWhenNoHrefIsGiven(assert, bot.action.tap); | |
| }); | |
| function doesNotEncodeReservedButAllowedCharactersInQuery(assert, action) { | |
| if (!checkActionCompatibility(action)) { | |
| assert.ok(true, 'Action not supported, skipping'); | |
| return; | |
| } | |
| var done = assert.async(); | |
| waitForLoad(iframe).then(function() { | |
| var domHelper = goog.dom.getDomHelper(iframeWindow); | |
| var clickTarget = domHelper.getElement('iframeClickTarget'); | |
| var targetHref = '?a=?/+'; | |
| clickTarget.href = targetHref; | |
| action(clickTarget); | |
| waitForLoad(iframe).then(function() { | |
| assert.strictEqual(iframeWindow.location.search, targetHref); | |
| done(); | |
| }); | |
| }); | |
| } | |
| QUnit.test('click does not encode reserved but allowed characters in query', function(assert) { | |
| doesNotEncodeReservedButAllowedCharactersInQuery(assert, bot.action.click); | |
| }); | |
| QUnit.test('tap does not encode reserved but allowed characters in query', function(assert) { | |
| doesNotEncodeReservedButAllowedCharactersInQuery(assert, bot.action.tap); | |
| }); | |
| function absoluteAnchorInAnIframeExecutesDefaultHandler(assert, action) { | |
| if (!checkActionCompatibility(action)) { | |
| assert.ok(true, 'Action not supported, skipping'); | |
| return; | |
| } | |
| var done = assert.async(); | |
| waitForLoad(iframe).then(function() { | |
| var clickTarget = getClickTarget('testdata/click_destination.html'); | |
| var targetHref = clickTarget.href; | |
| action(clickTarget); | |
| waitForLoad(iframe).then(function() { | |
| assert.strictEqual(iframeWindow.location.href, targetHref); | |
| done(); | |
| }); | |
| }); | |
| } | |
| QUnit.test('click absolute anchor in an iframe executes default handler', function(assert) { | |
| absoluteAnchorInAnIframeExecutesDefaultHandler(assert, bot.action.click); | |
| }); | |
| QUnit.test('tap absolute anchor in an iframe executes default handler', function(assert) { | |
| absoluteAnchorInAnIframeExecutesDefaultHandler(assert, bot.action.tap); | |
| }); | |
| function linkThatCausesContentToLoadInAnotherFrame(assert, action) { | |
| if (!checkActionCompatibility(action)) { | |
| assert.ok(true, 'Action not supported, skipping'); | |
| return; | |
| } | |
| var done = assert.async(); | |
| waitForLoad(iframe).then(function() { | |
| var clickTarget = getClickTarget('testdata/click_destination.html'); | |
| var targetHref = clickTarget.href; | |
| clickTarget.target = 'other'; | |
| action(clickTarget); | |
| waitForLoad(otherFrame).then(function() { | |
| assert.strictEqual(otherFrameWindow.location.href, targetHref); | |
| done(); | |
| }); | |
| }); | |
| } | |
| QUnit.test('click link that causes content to load in another frame', function(assert) { | |
| linkThatCausesContentToLoadInAnotherFrame(assert, bot.action.click); | |
| }); | |
| QUnit.test('tap link that causes content to load in another frame', function(assert) { | |
| linkThatCausesContentToLoadInAnotherFrame(assert, bot.action.tap); | |
| }); | |
| function onSelfPageReloadsPage(assert, action) { | |
| if (!checkActionCompatibility(action)) { | |
| assert.ok(true, 'Action not supported, skipping'); | |
| return; | |
| } | |
| var done = assert.async(); | |
| waitForLoad(iframe).then(function() { | |
| var clickTarget = getClickTarget(iframeWindow.location.href); | |
| var targetHref = clickTarget.href; | |
| action(clickTarget); | |
| waitForLoad(iframe).then(function() { | |
| assert.strictEqual(iframeWindow.location.href, targetHref); | |
| done(); | |
| }); | |
| }); | |
| } | |
| QUnit.test('click on self page reloads page', function(assert) { | |
| onSelfPageReloadsPage(assert, bot.action.click); | |
| }); | |
| QUnit.test('tap on self page reloads page', function(assert) { | |
| onSelfPageReloadsPage(assert, bot.action.tap); | |
| }); | |
| function actionOnHashDoesNotReloadThePage(assert, action) { | |
| if (!checkActionCompatibility(action)) { | |
| assert.ok(true, 'Action not supported, skipping'); | |
| return; | |
| } | |
| var done = assert.async(); | |
| waitForLoad(iframe).then(function() { | |
| var clickTarget = getClickTarget(''); | |
| clickTarget.href = '#'; | |
| var id = goog.events.listenOnce(iframe, 'load', function() { | |
| assert.ok(false, 'Did not expect iframe to load a new page'); | |
| done(); | |
| }); | |
| action(clickTarget); | |
| window.setTimeout(function() { | |
| goog.events.unlistenByKey(id); | |
| assert.ok(true); | |
| done(); | |
| }, 250); | |
| }); | |
| } | |
| QUnit.test('click on hash does not reload the page', function(assert) { | |
| actionOnHashDoesNotReloadThePage(assert, bot.action.click); | |
| }); | |
| QUnit.test('tap on hash does not reload the page', function(assert) { | |
| onSelfPageReloadsPage(assert, bot.action.tap); | |
| }); | |
| function focusOnAnElementBeforeFinishingClickSequence(assert, action) { | |
| if (!checkActionCompatibility(action)) { | |
| assert.ok(true, 'Action not supported, skipping'); | |
| return; | |
| } | |
| var done = assert.async(); | |
| goog.events.listenOnce(link, goog.events.EventType.FOCUS, function() { | |
| assert.ok(true); | |
| done(); | |
| }); | |
| action(link); | |
| } | |
| QUnit.test('click focus on an element before finishing click sequence', function(assert) { | |
| focusOnAnElementBeforeFinishingClickSequence(assert, bot.action.click); | |
| }); | |
| QUnit.test('tap focus on an element before finishing click sequence', function(assert) { | |
| focusOnAnElementBeforeFinishingClickSequence(assert, bot.action.tap); | |
| }); | |
| function focusOnAnElementWhenMousedownChangesFocus(assert, action) { | |
| if (!checkActionCompatibility(action)) { | |
| assert.ok(true, 'Action not supported, skipping'); | |
| return; | |
| } | |
| var mousedownPreemptsFocus = action == bot.action.tap ? false : | |
| goog.userAgent.GECKO || goog.userAgent.IE; | |
| goog.events.listen(link, goog.events.EventType.MOUSEDOWN, function() { | |
| link2.focus(); | |
| }); | |
| var done = assert.async(); | |
| var resolved = false; | |
| goog.events.listen(link, goog.events.EventType.FOCUS, function() { | |
| if (resolved) return; | |
| if (mousedownPreemptsFocus) { | |
| assert.ok(false, 'Did not expect link to be focused'); | |
| resolved = true; | |
| done(); | |
| } else { | |
| assert.ok(true); | |
| resolved = true; | |
| done(); | |
| } | |
| }); | |
| goog.events.listen(link2, goog.events.EventType.FOCUS, function() { | |
| if (resolved) return; | |
| if (mousedownPreemptsFocus) { | |
| window.setTimeout(function() { | |
| if (resolved) return; | |
| assert.ok(true); | |
| resolved = true; | |
| done(); | |
| }, 100); | |
| } | |
| }); | |
| action(link); | |
| } | |
| QUnit.test('click focus on an element when mousedown changes focus', function(assert) { | |
| focusOnAnElementWhenMousedownChangesFocus(assert, bot.action.click); | |
| }); | |
| QUnit.test('tap focus on an element when mousedown changes focus', function(assert) { | |
| focusOnAnElementWhenMousedownChangesFocus(assert, bot.action.tap); | |
| }); | |
| </script> | |
| </head> | |
| <body> | |
| <div id="qunit"></div> | |
| <div id="qunit-fixture"></div> | |
| <form action="javascript:void(0)"> | |
| <div id="log"></div> | |
| <script> | |
| divConsole = new goog.debug.DivConsole(goog.dom.$('log')); | |
| divConsole.setCapturing(true); | |
| </script> | |
| </form> | |
| <a id="clickTarget">Click me!</a> | |
| <a id="clickTargetWithNoHref">Click me!</a> | |
| <a id="clickTargetWithAChild">Click <strong>the nested</strong> element</a> | |
| <a id="clickTargetWithAChildAndNoHref">Click <strong>the nested</strong> element with no href</a> | |
| <a id="clickTargetWithInlineHandler" onclick="return false;">Click me, I will not follow the link!</a> | |
| <div> | |
| <div style="width:200px; height:100px; | |
| border:1px solid black; padding:10px">Click Me</div> | |
| </div> | |
| <iframe id="iframe"></iframe> | |
| <iframe id="other" name="other"></iframe> | |
| <a id="link" href="javascript:void(0)">link</a> | |
| <a id="link2" href="javascript:void(0)">link2</a> | |
| </body> | |
| </html> |