blob: b6f0185ab5a5c457a0118766d50aeaadd7951a7a [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Expire" content="0"/>
<title>click_link_test.html</title>
<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.Uri');
goog.require('goog.debug.DivConsole');
goog.require('goog.debug.Logger');
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.testing.AsyncTestCase');
goog.require('goog.testing.jsunit');
goog.require('goog.userAgent');
goog.require('goog.userAgent.product');
</script>
<script type="text/javascript">
var GECKO6 = goog.userAgent.GECKO && bot.userAgent.isEngineVersion(6);
var divConsole;
var iframe, iframeWindow, other, otherWindow;
var link, link2;
var findElement = bot.locators.findElement;
var findElements = bot.locators.findElements;
var log = goog.debug.Logger.getLogger('click_link_test');
var asyncTestCase = null;
function setUp() {
iframe = bot.locators.findElement({id: 'iframe'});
iframeWindow = goog.dom.getFrameContentWindow(iframe);
otherFrame = bot.locators.findElement({id: 'other'});
otherFrameWindow = goog.dom.getFrameContentWindow(otherFrame);
continueAfterLoad(iframe, goog.nullFunction);
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 continueAfterLoad(iframe, fn) {
asyncTestCase.waitForAsync('Waiting for ' + iframe.id + ' to load');
return goog.events.listenOnce(iframe, 'load', function() {
asyncTestCase.continueTesting();
fn();
});
}
function continueAfterTimeout(fn) {
asyncTestCase.waitForAsync('Waiting a cycle for page to update.');
window.setTimeout(function() {
asyncTestCase.continueTesting();
fn();
// Firefox 6 currently needs a fairly long timeout before a hashchange is
// completed, while other browsers complete it on the next event cycle.
// TODO(user): Remove superfluous link following from device.js and
// then check whether this longer timeout is still necessary.
}, GECKO6 ? 250 : 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(action) {
if (!checkActionCompatibility(action)) {
return;
}
var clickTarget = findElement({id: 'clickTarget'});
// Make sure no other event listeners are interfering.
goog.events.removeAll(clickTarget);
// Use a random value as we don't want to keep an old
// misleading hash in the url.
var targetHref = '#' + Math.random();
clickTarget.href = targetHref;
continueAfterTimeout(function() {
assertEquals(targetHref, window.location.hash);
});
action(clickTarget);
}
var testClickExecutesDefaultHandler =
goog.partial(executesDefaultHandler, bot.action.click);
var testTapExecutesDefaultHandler =
goog.partial(executesDefaultHandler, bot.action.tap);
function nestedElementExecutesDefaultHandler(action) {
if (!checkActionCompatibility(action)) {
return;
}
var parent = findElement({id: 'clickTargetWithAChild'});
// Use a random value as we don't want to keep an old
// misleading hash in the url.
var targetHref = '#' + Math.random();
parent.href = targetHref;
continueAfterTimeout(function() {
assertEquals(targetHref, window.location.hash);
});
var clickTarget = goog.dom.getFirstElementChild(parent);
action(clickTarget);
}
var testClickNestedElementExecutesDefaultHandler =
goog.partial(nestedElementExecutesDefaultHandler, bot.action.click);
var testTapNestedElementExecutesDefaultHandler =
goog.partial(nestedElementExecutesDefaultHandler, bot.action.tap);
function correctlyResolvesEmptyFragment(action) {
if (!checkActionCompatibility(action)) {
return;
}
// A bug in the closure goog.Uri module once prevented this from working.
var clickTarget = findElement({id: 'clickTarget'});
// Make sure no other event listeners are interfering.
goog.events.removeAll(clickTarget);
continueAfterTimeout(function() {
var windowHref = window.location.href;
assertEquals('#', windowHref.charAt(windowHref.length - 1));
});
clickTarget.href = '#';
action(clickTarget);
}
var testClickCorrectlyResolvesEmptyFragment =
goog.partial(correctlyResolvesEmptyFragment, bot.action.click);
var testTapCorrectlyResolvesEmptyFragment =
goog.partial(correctlyResolvesEmptyFragment, bot.action.tap);
function absoluteUrlInAnIframeExecutesDefaultHandler(action) {
if (!checkActionCompatibility(action)) {
return;
}
var domHelper = goog.dom.getDomHelper(iframeWindow);
var clickTarget = domHelper.getElement('iframeClickTarget');
// Use a random value as we don't want to keep an old
// misleading hash in the url.
var targetHref = goog.Uri.resolve(iframeWindow.location,
'#' + Math.random()).toString();
// Let's make sure it is an absolute url.
assertContains('http', targetHref);
clickTarget.href = targetHref;
action(clickTarget);
continueAfterTimeout(function() {
assertEquals(targetHref, iframeWindow.location.href);
});
}
var testClickAbsoluteUrlInAnIframeExecutesDefaultHandler =
goog.partial(absoluteUrlInAnIframeExecutesDefaultHandler,
bot.action.click);
var testTapAbsoluteUrlInAnIframeExecutesDefaultHandler =
goog.partial(absoluteUrlInAnIframeExecutesDefaultHandler,
bot.action.tap);
function absoluteServerPathAnchorInAnIframeExecutesDefaultHandler(action) {
if (!checkActionCompatibility(action)) {
return;
}
var domHelper = goog.dom.getDomHelper(iframeWindow);
var clickTarget = domHelper.getElement('iframeClickTarget');
// Use a random value as we don't want to keep an old
// misleading hash in the url.
var testPath = window.location.pathname;
var targetHref = testPath.substring(0, testPath.lastIndexOf('/')) +
'/testdata/click_iframe.html#' + Math.random();
clickTarget.href = targetHref;
action(clickTarget);
continueAfterTimeout(function() {
assertContains(targetHref, iframeWindow.location.href);
});
}
var testClickAbsoluteServerPathAnchorInAnIframeExecutesDefaultHandler =
goog.partial(absoluteServerPathAnchorInAnIframeExecutesDefaultHandler,
bot.action.click);
var testTapAbsoluteServerPathAnchorInAnIframeExecutesDefaultHandler =
goog.partial(absoluteServerPathAnchorInAnIframeExecutesDefaultHandler,
bot.action.tap);
function relativeServerPathAnchorInAnIframeExecutesDefaultHandler(action) {
if (!checkActionCompatibility(action)) {
return;
}
var domHelper = goog.dom.getDomHelper(iframeWindow);
var clickTarget = domHelper.getElement('iframeClickTarget');
// Use a random value as we don't want to keep an old
// misleading hash in the url.
var targetHref = 'click_iframe.html#' + Math.random();
clickTarget.href = targetHref;
action(clickTarget);
continueAfterTimeout(function() {
assertContains(targetHref, iframeWindow.location.href);
});
}
var testClickRelativeServerPathAnchorInAnIframeExecutesDefaultHandler =
goog.partial(relativeServerPathAnchorInAnIframeExecutesDefaultHandler,
bot.action.click);
var testTapRelativeServerPathAnchorInAnIframeExecutesDefaultHandler =
goog.partial(relativeServerPathAnchorInAnIframeExecutesDefaultHandler,
bot.action.tap);
function hashOnlyAnchorInAnIframeExecutesDefaultHandler(action) {
if (!checkActionCompatibility(action)) {
return;
}
var domHelper = goog.dom.getDomHelper(iframeWindow);
var clickTarget = domHelper.getElement('iframeClickTarget');
// Use a random value as we don't want to keep an old
// misleading hash in the url.
var targetHref = '#' + Math.random();
clickTarget.href = targetHref;
action(clickTarget);
continueAfterTimeout(function() {
assertEquals(targetHref, iframeWindow.location.hash);
});
}
var testClickHashOnlyAnchorInAnIframeExecutesDefaultHandler =
goog.partial(hashOnlyAnchorInAnIframeExecutesDefaultHandler,
bot.action.click);
var testTapHashOnlyAnchorInAnIframeExecutesDefaultHandler =
goog.partial(hashOnlyAnchorInAnIframeExecutesDefaultHandler,
bot.action.tap);
function nestedElementInAnIframeExecutesDefaultHandler(action) {
if (!checkActionCompatibility(action)) {
return;
}
var domHelper = goog.dom.getDomHelper(iframeWindow);
var parent = domHelper.getElement('iframeClickTargetWithAChild');
var clickTarget = goog.dom.getFirstElementChild(parent);
// Use a random value as we don't want to keep an old
// misleading hash in the url.
var targetHref = '#' + Math.random();
parent.href = targetHref;
action(clickTarget);
continueAfterTimeout(function() {
assertEquals(targetHref, iframeWindow.location.hash);
});
}
var testClickNestedElementInAnIframeExecutesDefaultHandler =
goog.partial(nestedElementInAnIframeExecutesDefaultHandler,
bot.action.click);
var testTapHashNestedElementInAnIframeExecutesDefaultHandler =
goog.partial(nestedElementInAnIframeExecutesDefaultHandler,
bot.action.tap);
function doesNotFollowLinkWhenEventDefaultPrevented(action) {
if (!checkActionCompatibility(action)) {
return;
}
var clickTarget = findElement({id: 'clickTarget'});
// Make sure no other event listeners are interfering.
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);
continueAfterTimeout(function() {
assertEquals(previousLocation, window.location.href);
});
}
var testClickDoesNotFollowLinkWhenEventDefaultPrevented =
goog.partial(doesNotFollowLinkWhenEventDefaultPrevented,
bot.action.click);
var testTapDoesNotFollowLinkWhenEventDefaultPrevented =
goog.partial(doesNotFollowLinkWhenEventDefaultPrevented,
bot.action.tap);
function doNotFollowLinkWhenEventDefaultPreventedWithInlineHandler(action) {
if (!checkActionCompatibility(action)) {
return;
}
var clickTarget = findElement({id: 'clickTargetWithInlineHandler'});
var previousLocation = window.location.href;
clickTarget.href = '#' + Math.random();
action(clickTarget);
continueAfterTimeout(function() {
assertEquals(previousLocation, window.location.href);
});
}
var testClickDoNotFollowLinkWhenEventDefaultPreventedWithInlineHandler =
goog.partial(doNotFollowLinkWhenEventDefaultPreventedWithInlineHandler,
bot.action.click);
var testTapDoNotFollowLinkWhenEventDefaultPreventedWithInlineHandler =
goog.partial(doNotFollowLinkWhenEventDefaultPreventedWithInlineHandler,
bot.action.tap);
function doesNotFollowLinkWhenNoHrefIsGiven(action) {
if (!checkActionCompatibility(action)) {
return;
}
var clickTarget = findElement({id: 'clickTargetWithNoHref'});
// Make sure no other event listeners are interfering.
goog.events.removeAll(clickTarget);
var previousLocation = window.location.href;
action(clickTarget);
continueAfterTimeout(function() {
assertEquals(previousLocation, window.location.href);
});
}
var testClickDoesNotFollowLinkWhenNoHrefIsGiven = goog.partial(
doesNotFollowLinkWhenNoHrefIsGiven, bot.action.click);
var testTapDoesNotFollowLinkWhenNoHrefIsGiven = goog.partial(
doesNotFollowLinkWhenNoHrefIsGiven, bot.action.tap);
function nestedElelementDoesNotFollowLinkWhenNoHrefIsGiven(action) {
if (!checkActionCompatibility(action)) {
return;
}
var clickTarget = findElement({id: 'clickTargetWithAChildAndNoHref'});
var previousLocation = window.location.href;
action(clickTarget);
assertContains(previousLocation, window.location.href);
}
var testClickNestedElelementDoesNotFollowLinkWhenNoHrefIsGiven =
goog.partial(nestedElelementDoesNotFollowLinkWhenNoHrefIsGiven,
bot.action.click);
var testTapNestedElelementDoesNotFollowLinkWhenNoHrefIsGiven =
goog.partial(nestedElelementDoesNotFollowLinkWhenNoHrefIsGiven,
bot.action.tap);
function doesNotEncodeReservedButAllowedCharactersInQuery(action) {
if (!checkActionCompatibility(action)) {
return;
}
// A bug in the closure goog.Uri module once prevented this from working.
var domHelper = goog.dom.getDomHelper(iframeWindow);
var clickTarget = domHelper.getElement('iframeClickTarget');
var targetHref = '?a=?/+';
clickTarget.href = targetHref;
continueAfterLoad(iframe, function() {
assertEquals(targetHref, iframeWindow.location.search);
});
action(clickTarget);
}
var testClickDoesNoteEncodeReservedButAllowedCharactersInQuery =
goog.partial(doesNotEncodeReservedButAllowedCharactersInQuery,
bot.action.click);
var testTapDoesNoteEncodeReservedButAllowedCharactersInQuery =
goog.partial(doesNotEncodeReservedButAllowedCharactersInQuery,
bot.action.tap);
function absoluteAnchorInAnIframeExecutesDefaultHandler(action) {
if (!checkActionCompatibility(action)) {
return;
}
var clickTarget = getClickTarget('testdata/click_destination.html');
var targetHref = clickTarget.href;
continueAfterLoad(iframe, function() {
assertEquals(targetHref, iframeWindow.location.href);
});
action(clickTarget);
}
var testClickAbsoluteAnchorInAnIframeExecutesDefaultHandler =
goog.partial(absoluteAnchorInAnIframeExecutesDefaultHandler,
bot.action.click);
var testTapAbsoluteAnchorInAnIframeExecutesDefaultHandler =
goog.partial(absoluteAnchorInAnIframeExecutesDefaultHandler,
bot.action.tap);
function linkThatCausesContentToLoadInAnotherFrame(action) {
if (!checkActionCompatibility(action)) {
return;
}
var clickTarget = getClickTarget('testdata/click_destination.html');
var targetHref = clickTarget.href;
clickTarget.target = 'other';
continueAfterLoad(otherFrame, function() {
assertEquals(targetHref, otherFrameWindow.location.href);
});
action(clickTarget);
}
var testClickLinkThatCausesContentToLoadInAnotherFrame =
goog.partial(linkThatCausesContentToLoadInAnotherFrame,
bot.action.click);
var testTapLinkThatCausesContentToLoadInAnotherFrame =
goog.partial(linkThatCausesContentToLoadInAnotherFrame,
bot.action.tap);
function onSelfPageReloadsPage(action) {
if (!checkActionCompatibility(action)) {
return;
}
var clickTarget = getClickTarget(iframeWindow.location.href);
var targetHref = clickTarget.href;
continueAfterLoad(iframe, function() {
assertEquals(targetHref, iframeWindow.location.href);
});
action(clickTarget);
}
var testClickOnSelfPageReloadsPage = goog.partial(onSelfPageReloadsPage,
bot.action.click);
var testTapOnSelfPageReloadsPage = goog.partial(onSelfPageReloadsPage,
bot.action.tap);
function actionOnHashDoesNotReloadThePage(action) {
if (!checkActionCompatibility(action)) {
return;
}
var clickTarget = getClickTarget('');
clickTarget.href = '#';
// Fail immediately if the iframe is loaded.
var id = continueAfterLoad(iframe, fail);
action(clickTarget);
// After a delay, assume page is not going to load and pass the test.
window.setTimeout(function() {
asyncTestCase.continueTesting();
goog.events.unlistenByKey(id);
}, 250);
}
var testClickOnHashDoesNotReloadThePage = goog.partial(
actionOnHashDoesNotReloadThePage, bot.action.click);
var testTapOnHashDoesNotReloadThePage = goog.partial(
onSelfPageReloadsPage, bot.action.tap);
function focusOnAnElementBeforeFinishingClickSequence(action) {
if (!checkActionCompatibility(action)) {
return;
}
goog.events.listen(link, goog.events.EventType.FOCUS, function() {
asyncTestCase.continueTesting();
});
asyncTestCase.waitForAsync('Waiting for link focus');
action(link);
}
var testClickFocusOnAnElementBeforeFinishingClickSequence = goog.partial(
focusOnAnElementBeforeFinishingClickSequence, bot.action.click);
var testTapFocusOnAnElementBeforeFinishingClickSequence = goog.partial(
focusOnAnElementBeforeFinishingClickSequence, bot.action.tap);
function focusOnAnElementWhenMousedownChangesFocus(action) {
if (!checkActionCompatibility(action)) {
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();
});
goog.events.listen(link, goog.events.EventType.FOCUS, function() {
asyncTestCase.continueTesting();
assert(!mousedownPreemptsFocus);
});
goog.events.listen(link2, goog.events.EventType.FOCUS, function() {
// If the mousedown will preempt the focus, delay the continue testing
// call for a short delay to make sure the above assert never triggers.
if (mousedownPreemptsFocus) {
window.setTimeout(function() {
asyncTestCase.continueTesting();
}, 100);
}
});
asyncTestCase.waitForAsync('Waiting for link focus');
action(link);
}
var testClickFocusOnAnElementWhenMousedownChangesFocus = goog.partial(
focusOnAnElementWhenMousedownChangesFocus, bot.action.click);
var testTapFocusOnAnElementWhenMousedownChangesFocus = goog.partial(
focusOnAnElementWhenMousedownChangesFocus, bot.action.tap);
</script>
</head>
<body>
<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>
<script>
asyncTestCase = goog.testing.AsyncTestCase.createAndInstall();
// Android needs a longer timeout due to emulator slowness.
// Opera 12, IE10, Firefox 10 are sometimes slow to load new iframe pages.
if (goog.userAgent.product.ANDROID) {
asyncTestCase.stepTimeout = 5000;
} else if ((goog.userAgent.product.OPERA &&
bot.userAgent.isEngineVersion(12)) ||
bot.userAgent.IE_DOC_10 ||
(goog.userAgent.GECKO &&
bot.userAgent.isEngineVersion(10))) {
asyncTestCase.stepTimeout = 2000;
}
</script>
<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>