blob: f493525c491710bcb19fa93d037e0c44a41852b5 [file] [log] [blame]
// Copyright 2010 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.ui.editor.LinkDialogTest');
goog.setTestOnly('goog.ui.editor.LinkDialogTest');
goog.require('goog.dom');
goog.require('goog.dom.DomHelper');
goog.require('goog.dom.TagName');
goog.require('goog.editor.BrowserFeature');
goog.require('goog.editor.Link');
goog.require('goog.events');
goog.require('goog.events.EventHandler');
goog.require('goog.events.EventType');
goog.require('goog.events.KeyCodes');
goog.require('goog.style');
goog.require('goog.testing.MockControl');
goog.require('goog.testing.PropertyReplacer');
goog.require('goog.testing.dom');
goog.require('goog.testing.events');
goog.require('goog.testing.events.Event');
goog.require('goog.testing.jsunit');
goog.require('goog.testing.mockmatchers');
goog.require('goog.testing.mockmatchers.ArgumentMatcher');
goog.require('goog.ui.editor.AbstractDialog');
goog.require('goog.ui.editor.LinkDialog');
goog.require('goog.ui.editor.messages');
goog.require('goog.userAgent');
var dialog;
var mockCtrl;
var mockLink;
var mockOkHandler;
var mockGetViewportSize;
var mockWindowOpen;
var isNew;
var anchorElem;
var stubs = new goog.testing.PropertyReplacer();
var ANCHOR_TEXT = 'anchor text';
var ANCHOR_URL = 'http://www.google.com/';
var ANCHOR_EMAIL = 'm@r.cos';
var ANCHOR_MAILTO = 'mailto:' + ANCHOR_EMAIL;
function setUp() {
anchorElem = goog.dom.createElement(goog.dom.TagName.A);
goog.dom.appendChild(goog.dom.getDocument().body, anchorElem);
mockCtrl = new goog.testing.MockControl();
mockLink = mockCtrl.createLooseMock(goog.editor.Link);
mockOkHandler = mockCtrl.createLooseMock(goog.events.EventHandler);
isNew = false;
mockLink.isNew();
mockLink.$anyTimes();
mockLink.$does(function() {
return isNew;
});
mockLink.getCurrentText();
mockLink.$anyTimes();
mockLink.$does(function() {
return anchorElem.innerHTML;
});
mockLink.setTextAndUrl(goog.testing.mockmatchers.isString,
goog.testing.mockmatchers.isString);
mockLink.$anyTimes();
mockLink.$does(function(text, url) {
anchorElem.innerHTML = text;
anchorElem.href = url;
});
mockLink.$registerArgumentListVerifier('placeCursorRightOf', function() {
return true;
});
mockLink.placeCursorRightOf(goog.testing.mockmatchers.iBoolean);
mockLink.$anyTimes();
mockLink.getAnchor();
mockLink.$anyTimes();
mockLink.$returns(anchorElem);
mockWindowOpen = mockCtrl.createFunctionMock('open');
stubs.set(window, 'open', mockWindowOpen);
}
function tearDown() {
dialog.dispose();
goog.dom.removeNode(anchorElem);
stubs.reset();
}
function setUpAnchor(href, text, opt_isNew, opt_target, opt_rel) {
anchorElem.href = href;
anchorElem.innerHTML = text;
isNew = !!opt_isNew;
if (opt_target) {
anchorElem.target = opt_target;
}
if (opt_rel) {
anchorElem.rel = opt_rel;
}
}
/**
* Creates and shows the dialog to be tested.
* @param {Document=} opt_document Document to render the dialog into.
* Defaults to the main window's document.
* @param {boolean=} opt_openInNewWindow Whether the open in new window
* checkbox should be shown.
* @param {boolean=} opt_noFollow Whether rel=nofollow checkbox should be
* shown.
*/
function createAndShow(opt_document, opt_openInNewWindow, opt_noFollow) {
dialog = new goog.ui.editor.LinkDialog(new goog.dom.DomHelper(opt_document),
mockLink);
if (opt_openInNewWindow) {
dialog.showOpenLinkInNewWindow(false);
}
if (opt_noFollow) {
dialog.showRelNoFollow();
}
dialog.addEventListener(goog.ui.editor.AbstractDialog.EventType.OK,
mockOkHandler);
dialog.show();
}
/**
* Sets up the mock event handler to expect an OK event with the given text
* and url.
*/
function expectOk(linkText, linkUrl, opt_openInNewWindow, opt_noFollow) {
mockOkHandler.handleEvent(new goog.testing.mockmatchers.ArgumentMatcher(
function(arg) {
return arg.type == goog.ui.editor.AbstractDialog.EventType.OK &&
arg.linkText == linkText &&
arg.linkUrl == linkUrl &&
arg.openInNewWindow == !!opt_openInNewWindow &&
arg.noFollow == !!opt_noFollow;
},
'{linkText: ' + linkText + ', linkUrl: ' + linkUrl +
', openInNewWindow: ' + opt_openInNewWindow +
', noFollow: ' + opt_noFollow + '}'));
}
/**
* Return true if we should use active element in our tests.
* @return {boolean} .
*/
function useActiveElement() {
return goog.editor.BrowserFeature.HAS_ACTIVE_ELEMENT ||
goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher(9);
}
/**
* Tests that when you show the dialog for a new link, you can switch
* to the URL view.
* @param {Document=} opt_document Document to render the dialog into.
* Defaults to the main window's document.
*/
function testShowNewLinkSwitchToUrl(opt_document) {
mockCtrl.$replayAll();
setUpAnchor('', '', true); // Must be done before creating the dialog.
createAndShow(opt_document);
var webRadio = dialog.dom.getElement(
goog.ui.editor.LinkDialog.Id_.ON_WEB_TAB).firstChild;
var emailRadio = dialog.dom.getElement(
goog.ui.editor.LinkDialog.Id_.EMAIL_ADDRESS_TAB).firstChild;
assertTrue('Web Radio Button selected', webRadio.checked);
assertFalse('Email Radio Button selected', emailRadio.checked);
if (useActiveElement()) {
assertEquals('Focus should be on url input',
getUrlInput(),
dialog.dom.getActiveElement());
}
emailRadio.click();
assertFalse('Web Radio Button selected', webRadio.checked);
assertTrue('Email Radio Button selected', emailRadio.checked);
if (useActiveElement()) {
assertEquals('Focus should be on url input',
getEmailInput(),
dialog.dom.getActiveElement());
}
mockCtrl.$verifyAll();
}
/**
* Tests that when you show the dialog for a new link, the input fields are
* empty, the web tab is selected and focus is in the url input field.
* @param {Document=} opt_document Document to render the dialog into.
* Defaults to the main window's document.
*/
function testShowForNewLink(opt_document) {
mockCtrl.$replayAll();
setUpAnchor('', '', true); // Must be done before creating the dialog.
createAndShow(opt_document);
assertEquals('Display text input field should be empty',
'',
getDisplayInputText());
assertEquals('Url input field should be empty',
'',
getUrlInputText());
assertEquals('On the web tab should be selected',
goog.ui.editor.LinkDialog.Id_.ON_WEB,
dialog.curTabId_);
if (useActiveElement()) {
assertEquals('Focus should be on url input',
getUrlInput(),
dialog.dom.getActiveElement());
}
mockCtrl.$verifyAll();
}
/**
* Fakes that the mock field is using an iframe and does the same test as
* testShowForNewLink().
*/
function testShowForNewLinkWithDiffAppWindow() {
testShowForNewLink(goog.dom.getElement('appWindowIframe').contentDocument);
}
/**
* Tests that when you show the dialog for a url link, the input fields are
* filled in, the web tab is selected and focus is in the url input field.
*/
function testShowForUrlLink() {
mockCtrl.$replayAll();
setUpAnchor(ANCHOR_URL, ANCHOR_TEXT);
createAndShow();
assertEquals('Display text input field should be filled in',
ANCHOR_TEXT,
getDisplayInputText());
assertEquals('Url input field should be filled in',
ANCHOR_URL,
getUrlInputText());
assertEquals('On the web tab should be selected',
goog.ui.editor.LinkDialog.Id_.ON_WEB,
dialog.curTabId_);
if (useActiveElement()) {
assertEquals('Focus should be on url input',
getUrlInput(),
dialog.dom.getActiveElement());
}
mockCtrl.$verifyAll();
}
/**
* Tests that when you show the dialog for a mailto link, the input fields are
* filled in, the email tab is selected and focus is in the email input field.
*/
function testShowForMailtoLink() {
mockCtrl.$replayAll();
setUpAnchor(ANCHOR_MAILTO, ANCHOR_TEXT);
createAndShow();
assertEquals('Display text input field should be filled in',
ANCHOR_TEXT,
getDisplayInputText());
assertEquals('Email input field should be filled in',
ANCHOR_EMAIL, // The 'mailto:' is not in the input!
getEmailInputText());
assertEquals('Email tab should be selected',
goog.ui.editor.LinkDialog.Id_.EMAIL_ADDRESS,
dialog.curTabId_);
if (useActiveElement()) {
assertEquals('Focus should be on email input',
getEmailInput(),
dialog.dom.getActiveElement());
}
mockCtrl.$verifyAll();
}
/**
* Tests that the display text is autogenerated from the url input in the
* right situations (and not generated when appropriate too).
*/
function testAutogeneration() {
mockCtrl.$replayAll();
setUpAnchor('', '', true);
createAndShow();
// Simulate typing a url when everything is empty, should autogen.
setUrlInputText(ANCHOR_URL);
assertEquals('Display text should have been autogenerated',
ANCHOR_URL,
getDisplayInputText());
// Simulate typing text when url is set, afterwards should not autogen.
setDisplayInputText(ANCHOR_TEXT);
setUrlInputText(ANCHOR_MAILTO);
assertNotEquals('Display text should not have been autogenerated',
ANCHOR_MAILTO,
getDisplayInputText());
assertEquals('Display text should have remained the same',
ANCHOR_TEXT,
getDisplayInputText());
// Simulate typing text equal to existing url, afterwards should autogen.
setDisplayInputText(ANCHOR_MAILTO);
setUrlInputText(ANCHOR_URL);
assertEquals('Display text should have been autogenerated',
ANCHOR_URL,
getDisplayInputText());
mockCtrl.$verifyAll();
}
/**
* Tests that the display text is not autogenerated from the url input in all
* situations when the autogeneration feature is turned off.
*/
function testAutogenerationOff() {
mockCtrl.$replayAll();
setUpAnchor('', '', true);
createAndShow();
// Disable the autogen feature
dialog.setAutogenFeatureEnabled(false);
// Simulate typing a url when everything is empty, should not autogen.
setUrlInputText(ANCHOR_URL);
assertEquals('Display text should not have been autogenerated',
'',
getDisplayInputText());
// Simulate typing text when url is set, afterwards should not autogen.
setDisplayInputText(ANCHOR_TEXT);
setUrlInputText(ANCHOR_MAILTO);
assertNotEquals('Display text should not have been autogenerated',
ANCHOR_MAILTO,
getDisplayInputText());
assertEquals('Display text should have remained the same',
ANCHOR_TEXT,
getDisplayInputText());
// Simulate typing text equal to existing url, afterwards should not
// autogen.
setDisplayInputText(ANCHOR_MAILTO);
setUrlInputText(ANCHOR_URL);
assertEquals('Display text should not have been autogenerated',
ANCHOR_MAILTO,
getDisplayInputText());
mockCtrl.$verifyAll();
}
/**
* Tests that clicking OK with the url tab selected dispatches an event with
* the proper link data.
*/
function testOkForUrl() {
expectOk(ANCHOR_TEXT, ANCHOR_URL);
mockCtrl.$replayAll();
setUpAnchor('', '', true);
createAndShow();
dialog.tabPane_.setSelectedTabId(goog.ui.editor.LinkDialog.Id_.ON_WEB_TAB);
setDisplayInputText(ANCHOR_TEXT);
setUrlInputText(ANCHOR_URL);
goog.testing.events.fireClickSequence(dialog.getOkButtonElement());
mockCtrl.$verifyAll();
}
/**
* Tests that clicking OK with the url tab selected but with an email address
* in the url field dispatches an event with the proper link data.
*/
function testOkForUrlWithEmail() {
expectOk(ANCHOR_TEXT, ANCHOR_MAILTO);
mockCtrl.$replayAll();
setUpAnchor('', '', true);
createAndShow();
dialog.tabPane_.setSelectedTabId(goog.ui.editor.LinkDialog.Id_.ON_WEB_TAB);
setDisplayInputText(ANCHOR_TEXT);
setUrlInputText(ANCHOR_EMAIL);
goog.testing.events.fireClickSequence(dialog.getOkButtonElement());
mockCtrl.$verifyAll();
}
/**
* Tests that clicking OK with the email tab selected dispatches an event with
* the proper link data.
*/
function testOkForEmail() {
expectOk(ANCHOR_TEXT, ANCHOR_MAILTO);
mockCtrl.$replayAll();
setUpAnchor('', '', true);
createAndShow();
dialog.tabPane_.setSelectedTabId(
goog.ui.editor.LinkDialog.Id_.EMAIL_ADDRESS_TAB);
setDisplayInputText(ANCHOR_TEXT);
setEmailInputText(ANCHOR_EMAIL);
goog.testing.events.fireClickSequence(dialog.getOkButtonElement());
mockCtrl.$verifyAll();
}
function testOpenLinkInNewWindowNewLink() {
expectOk(ANCHOR_TEXT, ANCHOR_URL, true);
expectOk(ANCHOR_TEXT, ANCHOR_URL, false);
mockCtrl.$replayAll();
setUpAnchor('', '', true);
createAndShow(undefined, true);
dialog.tabPane_.setSelectedTabId(goog.ui.editor.LinkDialog.Id_.ON_WEB_TAB);
setDisplayInputText(ANCHOR_TEXT);
setUrlInputText(ANCHOR_URL);
assertFalse('"Open in new window" should start unchecked',
getOpenInNewWindowCheckboxChecked());
setOpenInNewWindowCheckboxChecked(true);
assertTrue('"Open in new window" should have gotten checked',
getOpenInNewWindowCheckboxChecked());
goog.testing.events.fireClickSequence(dialog.getOkButtonElement());
// Reopen same dialog
dialog.show();
dialog.tabPane_.setSelectedTabId(goog.ui.editor.LinkDialog.Id_.ON_WEB_TAB);
setDisplayInputText(ANCHOR_TEXT);
setUrlInputText(ANCHOR_URL);
assertTrue('"Open in new window" should remember it was checked',
getOpenInNewWindowCheckboxChecked());
setOpenInNewWindowCheckboxChecked(false);
assertFalse('"Open in new window" should have gotten unchecked',
getOpenInNewWindowCheckboxChecked());
goog.testing.events.fireClickSequence(dialog.getOkButtonElement());
}
function testOpenLinkInNewWindowExistingLink() {
mockCtrl.$replayAll();
// Edit an existing link that already opens in a new window.
setUpAnchor('', '', false, '_blank');
createAndShow(undefined, true);
dialog.tabPane_.setSelectedTabId(goog.ui.editor.LinkDialog.Id_.ON_WEB_TAB);
setDisplayInputText(ANCHOR_TEXT);
setUrlInputText(ANCHOR_URL);
assertTrue('"Open in new window" should start checked for existing link',
getOpenInNewWindowCheckboxChecked());
mockCtrl.$verifyAll();
}
function testRelNoFollowNewLink() {
expectOk(ANCHOR_TEXT, ANCHOR_URL, null, true);
expectOk(ANCHOR_TEXT, ANCHOR_URL, null, false);
mockCtrl.$replayAll();
setUpAnchor('', '', true, true);
createAndShow(null, null, true);
dialog.tabPane_.setSelectedTabId(goog.ui.editor.LinkDialog.Id_.ON_WEB_TAB);
setDisplayInputText(ANCHOR_TEXT);
setUrlInputText(ANCHOR_URL);
assertFalse('rel=nofollow should start unchecked',
dialog.relNoFollowCheckbox_.checked);
// Check rel=nofollow and close the dialog.
dialog.relNoFollowCheckbox_.checked = true;
goog.testing.events.fireClickSequence(dialog.getOkButtonElement());
// Reopen the same dialog.
anchorElem.rel = 'foo nofollow bar';
dialog.show();
dialog.tabPane_.setSelectedTabId(goog.ui.editor.LinkDialog.Id_.ON_WEB_TAB);
setDisplayInputText(ANCHOR_TEXT);
setUrlInputText(ANCHOR_URL);
assertTrue('rel=nofollow should start checked when reopening the dialog',
dialog.relNoFollowCheckbox_.checked);
}
function testRelNoFollowExistingLink() {
mockCtrl.$replayAll();
setUpAnchor('', '', null, null, 'foo nofollow bar');
createAndShow(null, null, true);
assertTrue('rel=nofollow should start checked for existing link',
dialog.relNoFollowCheckbox_.checked);
mockCtrl.$verifyAll();
}
/**
* Test that clicking on the test button opens a new window with the correct
* options.
*/
function testWebTestButton() {
if (goog.userAgent.GECKO) {
// TODO(robbyw): Figure out why this is flaky and fix it.
return;
}
var width, height;
mockWindowOpen(ANCHOR_URL, '_blank',
new goog.testing.mockmatchers.ArgumentMatcher(function(str) {
return str == 'width=' + width + ',height=' + height +
',toolbar=1,scrollbars=1,location=1,statusbar=0,' +
'menubar=1,resizable=1';
}, '3rd arg: (string) window.open() options'));
mockCtrl.$replayAll();
setUpAnchor(ANCHOR_URL, ANCHOR_TEXT);
createAndShow();
// Measure viewport after opening dialog because that might cause scrollbars
// to appear and reduce the viewport size.
var size = goog.dom.getViewportSize(window);
width = Math.max(size.width - 50, 50);
height = Math.max(size.height - 50, 50);
var testLink = goog.testing.dom.findTextNode(
goog.ui.editor.messages.MSG_TEST_THIS_LINK,
dialog.dialogInternal_.getElement());
goog.testing.events.fireClickSequence(testLink.parentNode);
mockCtrl.$verifyAll();
}
/**
* Test that clicking on the test button does not open a new window when
* the event is canceled.
*/
function testWebTestButtonPreventDefault() {
mockCtrl.$replayAll();
setUpAnchor(ANCHOR_URL, ANCHOR_TEXT);
createAndShow();
goog.events.listen(dialog,
goog.ui.editor.LinkDialog.EventType.BEFORE_TEST_LINK,
function(e) {
assertEquals(e.url, ANCHOR_URL);
e.preventDefault();
});
var testLink = goog.testing.dom.findTextNode(
goog.ui.editor.messages.MSG_TEST_THIS_LINK,
dialog.dialogInternal_.getElement());
goog.testing.events.fireClickSequence(testLink.parentNode);
mockCtrl.$verifyAll();
}
/**
* Test that the setTextToDisplayVisible() correctly works.
* options.
*/
function testSetTextToDisplayVisible() {
mockCtrl.$replayAll();
setUpAnchor('', '', true);
createAndShow();
assertNotEquals('none',
goog.style.getStyle(dialog.textToDisplayDiv_, 'display'));
dialog.setTextToDisplayVisible(false);
assertEquals('none',
goog.style.getStyle(dialog.textToDisplayDiv_, 'display'));
dialog.setTextToDisplayVisible(true);
assertNotEquals('none',
goog.style.getStyle(dialog.textToDisplayDiv_, 'display'));
mockCtrl.$verifyAll();
}
function getDisplayInput() {
return dialog.dom.getElement(goog.ui.editor.LinkDialog.Id_.TEXT_TO_DISPLAY);
}
function getDisplayInputText() {
return getDisplayInput().value;
}
function setDisplayInputText(text) {
var textInput = getDisplayInput();
textInput.value = text;
// Fire event so that dialog behaves like when user types.
fireInputEvent(textInput, goog.events.KeyCodes.M);
}
function getUrlInput() {
var elt = dialog.dom.getElement(goog.ui.editor.LinkDialog.Id_.ON_WEB_INPUT);
assertNotNullNorUndefined('UrlInput must be found', elt);
return elt;
}
function getUrlInputText() {
return getUrlInput().value;
}
function setUrlInputText(text) {
var urlInput = getUrlInput();
urlInput.value = text;
// Fire event so that dialog behaves like when user types.
fireInputEvent(dialog.urlInputHandler_, goog.events.KeyCodes.M);
}
function getEmailInput() {
var elt = dialog.dom.getElement(
goog.ui.editor.LinkDialog.Id_.EMAIL_ADDRESS_INPUT);
assertNotNullNorUndefined('EmailInput must be found', elt);
return elt;
}
function getEmailInputText() {
return getEmailInput().value;
}
function setEmailInputText(text) {
var emailInput = getEmailInput();
emailInput.value = text;
// Fire event so that dialog behaves like when user types.
fireInputEvent(dialog.emailInputHandler_, goog.events.KeyCodes.M);
}
function getOpenInNewWindowCheckboxChecked() {
return dialog.openInNewWindowCheckbox_.checked;
}
function setOpenInNewWindowCheckboxChecked(checked) {
dialog.openInNewWindowCheckbox_.checked = checked;
}
function fireInputEvent(input, keyCode) {
var inputEvent = new goog.testing.events.Event(goog.events.EventType.INPUT,
input);
inputEvent.keyCode = keyCode;
inputEvent.charCode = keyCode;
goog.testing.events.fireBrowserEvent(inputEvent);
}