[Pkg-mozext-commits] [compactheader] 235/441: Reorganized toolbar functions. Created first set of mozmill tests.
David Prévot
taffit at moszumanska.debian.org
Wed Mar 18 12:29:02 UTC 2015
This is an automated email from the git hooks/post-receive script.
taffit pushed a commit to branch master
in repository compactheader.
commit 7175d10056c3d5cce1861ccf45fe8dda7171e9ed
Author: joachim <none at none>
Date: Sat Jul 30 16:22:56 2011 +0200
Reorganized toolbar functions.
Created first set of mozmill tests.
--HG--
branch : mozmill
---
.hgignore | 6 +-
chrome/CompactHeader/content/CHTMessenger.js | 71 +-
.../CompactHeader/content/compactHeaderOverlay.js | 30 +-
.../CompactHeader/content/compactHeaderOverlay.xul | 36 +-
.../content/customizeToolbarOverlay.xul | 4 +-
chrome/CompactHeader/content/toolbar.js | 77 +-
test/compactheader/test-compactheader-toolbar.js | 604 +++++++++++++++
test/compactheader/test-message-header.js | 837 +++++++++++++++++++++
test/compactheader/test-mouse-event-helpers.js | 220 ++++++
test/download.sh | 20 +
10 files changed, 1801 insertions(+), 104 deletions(-)
diff --git a/.hgignore b/.hgignore
index 5b87d2a..32e23f8 100644
--- a/.hgignore
+++ b/.hgignore
@@ -1,3 +1,7 @@
syntax: regexp
-^AMO$
\ No newline at end of file
+^AMO$
+syntax: regexp
+^test/ftp$
+syntax: regexp
+^test/test-.*
\ No newline at end of file
diff --git a/chrome/CompactHeader/content/CHTMessenger.js b/chrome/CompactHeader/content/CHTMessenger.js
index fcac6fb..8d230db 100644
--- a/chrome/CompactHeader/content/CHTMessenger.js
+++ b/chrome/CompactHeader/content/CHTMessenger.js
@@ -49,12 +49,12 @@ org.mozdev.customizeHeaderToolbar.messenger = function(){
// var onLoadFkt = document.getElementById("messengerWindow").getAttribute("onload");
// if (onLoadFkt) {
// var strTest = new RegExp('OnLoadMessenger', 'g');;
-// onLoadFkt = onLoadFkt.replace(strTest,
+// onLoadFkt = onLoadFkt.replace(strTest,
// "org.mozdev.customizeHeaderToolbar.messenger.CHTLoadMessenger");
// document.getElementById("messengerWindow").setAttribute("onload", onLoadFkt);
// }
// }
-
+
pub.saveToolboxData = function() {
var hdrToolbox = document.getElementById("header-view-toolbox");
var hdrToolbar = document.getElementById("header-view-toolbar");
@@ -89,7 +89,7 @@ org.mozdev.customizeHeaderToolbar.messenger = function(){
saveToolbox.setAttribute("gotData", "false");
}
}
-
+
pub.loadToolboxData = function() {
var hdrToolbox = document.getElementById("header-view-toolbox");
var hdrToolbar = document.getElementById("header-view-toolbar");
@@ -106,72 +106,9 @@ org.mozdev.customizeHeaderToolbar.messenger = function(){
hdrToolbox.toolbarset = saveToolbox.toolbarset.cloneNode(true);
} else {
}
- }
+ }
}
-
-
- return pub;
-}();
-org.mozdev.customizeHeaderToolbar.pane = function(){
- var pub = {};
-
- pub.CHTUpdateReplyButton = function () {
- UpdateReplyButtons();
- }
-
- pub.CHTUpdateJunkButton = function () {
- UpdateJunkButton();
- }
-
- pub.CHTSetDefaultButtons = function () {
- var hdrToolbox = document.getElementById("header-view-toolbox");
- var hdrToolbar = document.getElementById("header-view-toolbar");
- var hdrBarDefaultSet = hdrToolbar.getAttribute("defaultset");
- var hdrBoxDefaultLabelalign = hdrToolbox.getAttribute("defaultlabelalign");
- var hdrBoxDefaultIconsize = hdrToolbox.getAttribute("defaulticonsize");
- var hdrBoxDefaultMode = hdrToolbox.getAttribute("defaultmode");
- var hdrBarDefaultIconsize = hdrToolbar.getAttribute("defaulticonsize");
- var hdrBarDefaultMode = hdrToolbar.getAttribute("defaultmode");
-
- hdrToolbox.setAttribute("labelalign", hdrBoxDefaultLabelalign);
- hdrToolbox.setAttribute("iconsize", hdrBoxDefaultIconsize);
- hdrToolbox.setAttribute("mode", hdrBoxDefaultMode);
- hdrToolbar.setAttribute("iconsize", hdrBarDefaultIconsize);
- hdrToolbar.setAttribute("mode", hdrBarDefaultMode);
-
- hdrToolbar.currentSet = hdrBarDefaultSet;
- hdrToolbar.setAttribute("currentset", hdrBarDefaultSet);
-
- document.persist(hdrToolbox.id,"labelalign");
- document.persist(hdrToolbox.id,"iconsize");
- document.persist(hdrToolbox.id,"mode");
- document.persist(hdrToolbar.id,"iconsize");
- document.persist(hdrToolbar.id,"mode");
- document.persist(hdrToolbar.id,"currentset");
- }
-
- pub.CHTCleanupButtons = function() {
- var hdrToolbox = document.getElementById("header-view-toolbox");
- var hdrToolbar = document.getElementById("header-view-toolbar");
- var hdrBarDefaultSet = "hdrReplyToSenderButton,hdrSmartReplyButton,hdrForwardButton,hdrArchiveButton,hdrJunkButton,hdrTrashButton";
-
- hdrToolbox.setAttribute("labelalign", "end");
- hdrToolbox.setAttribute("iconsize", "small");
- hdrToolbox.setAttribute("mode", "full");
-
- hdrToolbar.setAttribute("iconsize", "small");
- hdrToolbar.setAttribute("mode", "full");
- hdrToolbar.currentSet = hdrBarDefaultSet;
- hdrToolbar.setAttribute("currentset", hdrBarDefaultSet);
-
- document.persist(hdrToolbox.id,"labelalign");
- document.persist(hdrToolbox.id,"iconsize");
- document.persist(hdrToolbox.id,"mode");
- document.persist(hdrToolbar.id,"iconsize");
- document.persist(hdrToolbar.id,"mode");
- document.persist(hdrToolbar.id,"currentset");
- }
return pub;
}();
diff --git a/chrome/CompactHeader/content/compactHeaderOverlay.js b/chrome/CompactHeader/content/compactHeaderOverlay.js
index c490cfc..634240b 100644
--- a/chrome/CompactHeader/content/compactHeaderOverlay.js
+++ b/chrome/CompactHeader/content/compactHeaderOverlay.js
@@ -246,8 +246,8 @@ org.mozdev.compactHeader.pane = function() {
MailToolboxCustomizeDone(aEvent, "CustomizeHeaderToolbar");
document.getElementById("header-view-toolbox").removeAttribute("doCustomization");
enableButtons();
- org.mozdev.customizeHeaderToolbar.pane.CHTUpdateReplyButton();
- org.mozdev.customizeHeaderToolbar.pane.CHTUpdateJunkButton();
+ org.mozdev.compactHeader.toolbar.CHTUpdateReplyButton();
+ org.mozdev.compactHeader.toolbar.CHTUpdateJunkButton();
org.mozdev.compactHeader.buttons.coheToggleStar();
org.mozdev.customizeHeaderToolbar.messenger.saveToolboxData();
};
@@ -344,8 +344,8 @@ org.mozdev.compactHeader.pane = function() {
//org.mozdev.compactHeader.toolbar.fillToolboxPalette(document);
coheToggleHeaderContent();
- org.mozdev.customizeHeaderToolbar.pane.CHTUpdateReplyButton();
- org.mozdev.customizeHeaderToolbar.pane.CHTUpdateJunkButton();
+ org.mozdev.compactHeader.toolbar.CHTUpdateReplyButton();
+ org.mozdev.compactHeader.toolbar.CHTUpdateJunkButton();
org.mozdev.compactHeader.buttons.coheToggleStar();
}
@@ -590,7 +590,8 @@ org.mozdev.compactHeader.pane = function() {
.getService(Components.interfaces.nsIVersionComparator);
// org.mozdev.compactHeader.debug.log("first run 0");
if(versionChecker.compare(appInfo.version, "3.2a1pre") < 0) {
-// org.mozdev.compactHeader.debug.log("firstrun 1");
+ org.mozdev.compactHeader.debug.log("firstrun 1");
+ org.mozdev.compactHeader.toolbar.populateEmptyToolbar();
cohe.version = -1;
cohe.firstrun = false;
cohe.gExtensionManager = Components.classes["@mozilla.org/extensions/manager;1"].getService(Components.interfaces.nsIExtensionManager);
@@ -611,7 +612,7 @@ org.mozdev.compactHeader.pane = function() {
if (cohe.firstrun){
cohePrefBranch.setBoolPref("firstrun",false);
cohePrefBranch.setCharPref("version",cohe.current);
- org.mozdev.customizeHeaderToolbar.pane.CHTSetDefaultButtons();
+ org.mozdev.compactHeader.toolbar.CHTSetDefaultButtons();
}
//check for upgrade
if (cohe.version!=cohe.current && !cohe.firstrun){
@@ -624,12 +625,13 @@ org.mozdev.compactHeader.pane = function() {
}
}
else {
- //org.mozdev.compactHeader.debug.log("firstrun 3");
+ org.mozdev.compactHeader.debug.log("firstrun 3");
+ org.mozdev.compactHeader.toolbar.populateEmptyToolbar();
Components.utils.import("resource://gre/modules/AddonManager.jsm");
AddonManager.getAddonByID(COHE_EXTENSION_UUID,
function(myAddon) {
-// org.mozdev.compactHeader.debug.log("first run 2");
- cohe.version = -1;
+ org.mozdev.compactHeader.debug.log("first run 2");
+ cohe.version = "";
cohe.firstrun = false;
cohe.current = myAddon.version;
try{
@@ -639,14 +641,16 @@ org.mozdev.compactHeader.pane = function() {
} finally {
//check for first run
if (cohe.firstrun){
-// org.mozdev.compactHeader.debug.log("first run 2c");
- org.mozdev.customizeHeaderToolbar.pane.CHTSetDefaultButtons();
+ org.mozdev.compactHeader.debug.log("first run 2c");
+ org.mozdev.compactHeader.toolbar.CHTSetDefaultButtons();
cohePrefBranch.setBoolPref("firstrun",false);
cohePrefBranch.setCharPref("version",cohe.current);
+ org.mozdev.compactHeader.debug.log("first run 2cc");
}
//check for upgrade
if (cohe.version!=cohe.current && !cohe.firstrun){
cohePrefBranch.setCharPref("version",cohe.current);
+ org.mozdev.compactHeader.debug.log("found version change");
// XXX
}
cohe.firstrun = false;
@@ -655,7 +659,7 @@ org.mozdev.compactHeader.pane = function() {
}
);
}
-// org.mozdev.compactHeader.debug.log("firstrun 4");
+ org.mozdev.compactHeader.debug.log("firstrun 4");
}
@@ -688,7 +692,7 @@ org.mozdev.compactHeader.pane = function() {
org.mozdev.compactHeader.debug.log("uninstalling COHE 2");
if (this._uninstall) {
cohePrefBranch.deleteBranch("");
- org.mozdev.customizeHeaderToolbar.pane.CHTCleanupButtons();
+ org.mozdev.compactHeader.toolbar.CHTCleanupButtons();
}
this.unregister();
}
diff --git a/chrome/CompactHeader/content/compactHeaderOverlay.xul b/chrome/CompactHeader/content/compactHeaderOverlay.xul
index fd01513..7b75974 100644
--- a/chrome/CompactHeader/content/compactHeaderOverlay.xul
+++ b/chrome/CompactHeader/content/compactHeaderOverlay.xul
@@ -1,8 +1,8 @@
<?xml version="1.0" ?>
<!DOCTYPE overlay [
- <!ENTITY % msgHeaderDTD SYSTEM
- "chrome://messenger/locale/msgHdrViewOverlay.dtd">
+ <!ENTITY % msgHeaderDTD SYSTEM
+ "chrome://messenger/locale/msgHdrViewOverlay.dtd">
%msgHeaderDTD;
<!ENTITY % compactHeaderDTD SYSTEM
"chrome://CompactHeader/locale/CompactHeader.dtd">
@@ -25,19 +25,17 @@
<script type="application/javascript" src="chrome://CompactHeader/content/compactHeaderOverlay.js"/>
<script type="application/javascript" src="chrome://CompactHeader/content/RSSLinkify.js"/>
<script type="application/javascript" src="chrome://CompactHeader/content/toolbar.js"/>
- <script type="application/x-javascript"
- src="chrome://CompactHeader/content/CHTMessenger.js"/>
<script type="application/javascript" src="chrome://CompactHeader/content/buttonsOverlay.js"/>
<keyset>
- <key id="hideDetailsKey"
- modifiers="shift"
+ <key id="hideDetailsKey"
+ modifiers="shift"
key="&toggleDetails.key;"
oncommand="org.mozdev.compactHeader.pane.coheToggleHeaderView();"/>
</keyset>
<menupopup id="header-toolbar-context-menu">
- <menuitem id="hidecohePreferencesButton"
+ <menuitem id="hidecohePreferencesButton"
label="&dialog.title;"
oncommand="openDialog('chrome://CompactHeader/content/preferences.xul', 'prefs', 'chrome,resizable=no,centerscreen,modal');"/>
</menupopup>
@@ -46,9 +44,9 @@
<vbox id="expandedHeaderView" orient="horizontal">
<vbox id="hideDetailsButtonBox" insertbefore="expandedHeadersBox">
- <button id="hideDetailsButton"
+ <button id="hideDetailsButton"
tooltiptext="&hideDetailsButton.label;"
- onclick="org.mozdev.compactHeader.pane.coheToggleHeaderView();"
+ onclick="org.mozdev.compactHeader.pane.coheToggleHeaderView();"
class="msgHeaderView-flat-button"/>
</vbox>
@@ -57,7 +55,7 @@
<label id="CoheShowDetailsLabel" value="&showDetailsButton.label;"/>
</hbox>
- <vbox id="expandedHeadersBox">
+ <vbox id="expandedHeadersBox">
<hbox id="expandedHeadersTopBox" flex="1">
<toolbox id="header-view-toolbox"
mode="icons"
@@ -71,14 +69,14 @@
</toolbarpalette>
<toolbar id="header-view-toolbar"
mode="icons" defaultmode="icons"
- defaultset="hdrReplyToSenderButton,hdrReplyButton,hdrReplyAllButton,hdrReplyListButton,hdrForwardButton,button-reply,button-forward,hdrArchiveButton,hdrJunkButton,hdrTrashButton,hdrOtherActionsButton">
+ defaultset="hdrReplyToSenderButton,hdrForwardButton,button-reply,button-forward,hdrArchiveButton,hdrJunkButton,hdrTrashButton,hdrOtherActionsButton">
</toolbar>
</toolbox>
</hbox>
<hbox id="expandedHeadersBottomBox">
-
+
<vbox id="otherActionsBox" flex="0">
<hbox id="dateValueBox" flex="0"/>
<button type="menu" id="otherActionsButton" collapsed="true"
@@ -109,17 +107,17 @@
</menupopup>
</menu>
<menuseparator id="otherActionPopupAfterViewSource"/>
- <menuitem id="hideDetailsMenu"
+ <menuitem id="hideDetailsMenu"
label="&hideDetailsButton.label;"
oncommand="org.mozdev.compactHeader.pane.coheToggleHeaderView();"/>
- <menuitem id="hidecohePreferencesButton"
+ <menuitem id="hidecohePreferencesButton"
label="&dialog.title;"
oncommand="openDialog('chrome://CompactHeader/content/preferences.xul', 'prefs', 'chrome,centerscreen,dependent,all,resizable=no');"/>
</menupopup>
</button>
</vbox>
</hbox>
-
+
</vbox>
<vbox id="dispMUAexp" collapsed="false">
@@ -165,7 +163,7 @@
<column flex="1"/>
</columns>
<row id="collapsed1LtoCcBccRow" align="baseline">
- <label id="collapsed1LtoCcBccLabel" class="headerName"
+ <label id="collapsed1LtoCcBccLabel" class="headerName"
value="&toField2.label;" control="collapsed1LtoCcBccBox"/>
<mail-multi-emailHeaderField id="collapsed1LtoCcBccBox" flex="1"/>
</row>
@@ -175,7 +173,7 @@
<row id="collapsed1LdateRow">
<label id="collapsed1LdateBox" class="dateLabel" flex="1"/>
</row>
- </hbox>
+ </hbox>
<header-view-button-box id="collapsed1LButtonBox" flex="0" align="start" hidden="true"/>
</hbox>
<hbox id="collapsed1LHeaderViewSecondLine" align="top" flex="1" collapsed="true">
@@ -203,7 +201,7 @@
</columns>
<rows>
<row id="collapsed2LtoCcBccRow" align="baseline">
- <label id="collapsed2LtoCcBccLabel" class="headerName"
+ <label id="collapsed2LtoCcBccLabel" class="headerName"
value="&toField2.label;" control="collapsed2LtoCcBccBox"/>
<mail-multi-emailHeaderField id="collapsed2LtoCcBccBox" flex="1"/>
</row>
@@ -243,5 +241,5 @@
</overlay>
-<!--
+<!--
-->
\ No newline at end of file
diff --git a/chrome/CompactHeader/content/customizeToolbarOverlay.xul b/chrome/CompactHeader/content/customizeToolbarOverlay.xul
index 39aef22..35246f5 100644
--- a/chrome/CompactHeader/content/customizeToolbarOverlay.xul
+++ b/chrome/CompactHeader/content/customizeToolbarOverlay.xul
@@ -2,7 +2,7 @@
<!DOCTYPE overlay [
<!ENTITY % customizeToolbarDTD SYSTEM "chrome://global/locale/customizeToolbar.dtd">
- %customizeToolbarDTD;
+ %customizeToolbarDTD;
]>
<?xml-stylesheet href="chrome://CompactHeader-os/skin/osdef.css" type="text/css"?>
@@ -15,4 +15,6 @@
<script type="application/javascript" src="chrome://CompactHeader/content/RSSLinkify.js"/>
<script type="application/javascript" src="chrome://CompactHeader/content/toolbar.js"/>
+ <window id="CustomizeToolbarWindow"
+ windowtype="mail:customizetoolbar"/>
</overlay>
diff --git a/chrome/CompactHeader/content/toolbar.js b/chrome/CompactHeader/content/toolbar.js
index 6e7f167..6e3e7cc 100644
--- a/chrome/CompactHeader/content/toolbar.js
+++ b/chrome/CompactHeader/content/toolbar.js
@@ -418,12 +418,12 @@ org.mozdev.compactHeader.toolbar = function() {
if (!testnew) {
el.className += el.className?' '+strClass:strClass;
}
- }
+ };
function removeClass(el, strClass) {
var str = new RegExp('(\\s|^)'+strClass+'(\\s|$)', 'g');
el.className = el.className.replace(str, ' ');
- }
+ };
function flatButtons() {
var result = cohePrefBranch.getBoolPref("headersize.flatButtons");
@@ -431,7 +431,78 @@ org.mozdev.compactHeader.toolbar = function() {
result = false;
}
return result;
- }
+ };
+
+ pub.CHTUpdateReplyButton = function () {
+ UpdateReplyButtons();
+ };
+
+ pub.CHTUpdateJunkButton = function () {
+ UpdateJunkButton();
+ };
+
+ pub.CHTSetDefaultButtons = function () {
+ var hdrToolbox = document.getElementById("header-view-toolbox");
+ var hdrToolbar = document.getElementById("header-view-toolbar");
+ var hdrBarDefaultSet = hdrToolbar.getAttribute("defaultset");
+ var hdrBoxDefaultLabelalign = hdrToolbox.getAttribute("defaultlabelalign");
+ var hdrBoxDefaultIconsize = hdrToolbox.getAttribute("defaulticonsize");
+ var hdrBoxDefaultMode = hdrToolbox.getAttribute("defaultmode");
+ var hdrBarDefaultIconsize = hdrToolbar.getAttribute("defaulticonsize");
+ var hdrBarDefaultMode = hdrToolbar.getAttribute("defaultmode");
+
+ hdrToolbox.setAttribute("labelalign", hdrBoxDefaultLabelalign);
+ hdrToolbox.setAttribute("iconsize", hdrBoxDefaultIconsize);
+ hdrToolbox.setAttribute("mode", hdrBoxDefaultMode);
+ hdrToolbar.setAttribute("iconsize", hdrBarDefaultIconsize);
+ hdrToolbar.setAttribute("mode", hdrBarDefaultMode);
+
+ hdrToolbar.currentSet = hdrBarDefaultSet;
+ hdrToolbar.setAttribute("currentset", hdrBarDefaultSet);
+
+ document.persist(hdrToolbox.id,"labelalign");
+ document.persist(hdrToolbox.id,"iconsize");
+ document.persist(hdrToolbox.id,"mode");
+ document.persist(hdrToolbar.id,"iconsize");
+ document.persist(hdrToolbar.id,"mode");
+ document.persist(hdrToolbar.id,"currentset");
+ };
+
+ pub.CHTCleanupButtons = function() {
+ var hdrToolbox = document.getElementById("header-view-toolbox");
+ var hdrToolbar = document.getElementById("header-view-toolbar");
+ var hdrBarDefaultSet = "hdrReplyToSenderButton,hdrSmartReplyButton,hdrForwardButton,hdrArchiveButton,hdrJunkButton,hdrTrashButton";
+
+ hdrToolbox.setAttribute("labelalign", "end");
+ hdrToolbox.setAttribute("iconsize", "small");
+ hdrToolbox.setAttribute("mode", "full");
+
+ hdrToolbar.setAttribute("iconsize", "small");
+ hdrToolbar.setAttribute("mode", "full");
+ hdrToolbar.currentSet = hdrBarDefaultSet;
+ hdrToolbar.setAttribute("currentset", hdrBarDefaultSet);
+
+ document.persist(hdrToolbox.id,"labelalign");
+ document.persist(hdrToolbox.id,"iconsize");
+ document.persist(hdrToolbox.id,"mode");
+ document.persist(hdrToolbar.id,"iconsize");
+ document.persist(hdrToolbar.id,"mode");
+ document.persist(hdrToolbar.id,"currentset");
+ };
+
+ pub.populateEmptyToolbar = function() {
+ org.mozdev.compactHeader.debug.log("start populateEmptyToolbar");
+ var hdrToolbar = document.getElementById("header-view-toolbar");
+ if (hdrToolbar) {
+ org.mozdev.compactHeader.debug.log("populateEmptyToolbar 1");
+ if (hdrToolbar.currentSet == "__empty") {
+ org.mozdev.compactHeader.debug.log("populateEmptyToolbar 2");
+ pub.CHTSetDefaultButtons();
+ }
+ }
+ org.mozdev.compactHeader.debug.log("stop populateEmptyToolbar");
+ };
+
return pub;
}();
diff --git a/test/compactheader/test-compactheader-toolbar.js b/test/compactheader/test-compactheader-toolbar.js
new file mode 100644
index 0000000..bf072af
--- /dev/null
+++ b/test/compactheader/test-compactheader-toolbar.js
@@ -0,0 +1,604 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Thunderbird Mail Client.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Blake Winton <bwinton at latte.ca>
+ * Dan Mosedale <dmose at mozillamessaging.com>
+ * Joachim Herb <Joachim.Herb at gmx.de>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Test that we can add a tag to a message without messing up the header.
+ */
+var MODULE_NAME = 'test-header-toolbar';
+
+var RELATIVE_ROOT = '../shared-modules';
+var MODULE_REQUIRES = ['folder-display-helpers', 'window-helpers',
+ 'address-book-helpers', 'mouse-event-helpers'];
+
+var elib = {};
+Cu.import('resource://mozmill/modules/elementslib.js', elib);
+var controller = {};
+Cu.import('resource://mozmill/modules/controller.js', controller);
+
+// The WindowHelper module
+var WindowHelper;
+
+var folder;
+
+const PREF = "toolbar.customization.usesheet";
+var prefBranch = Cc["@mozilla.org/preferences-service;1"]
+ .getService(Ci.nsIPrefService).getBranch(null);
+
+function setupModule(module) {
+ let fdh = collector.getModule('folder-display-helpers');
+ fdh.installInto(module);
+ WindowHelper = collector.getModule('window-helpers');
+ WindowHelper.installInto(module);
+ let abh = collector.getModule('address-book-helpers');
+ abh.installInto(module);
+ let meh = collector.getModule('mouse-event-helpers');
+ meh.installInto(module);
+
+ folder = create_folder("MessageWindowB");
+
+ // create a message that has the interesting headers that commonly
+ // show up in the message header pane for testing
+ let msg = create_message({cc: msgGen.makeNamesAndAddresses(20), // YYY
+ subject: "This is a really, really, really, really, really, really, really, really, long subject.",
+ clobberHeaders: {
+ "Newsgroups": "alt.test",
+ "Reply-To": "J. Doe <j.doe at momo.invalid>",
+ "Content-Base": "http://example.com/",
+ "Bcc": "Richard Roe <richard.roe at momo.invalid>"
+ }});
+
+ add_message_to_folder(folder, msg);
+
+ // create a message that has boring headers to be able to switch to and
+ // back from, to force the more button to collapse again.
+ msg = create_message();
+ add_message_to_folder(folder, msg);
+}
+
+
+/**
+ * Make sure that opening the header toolbar customization dialog
+ * does not break the get messages button in main toolbar
+ */
+//function test_get_msg_button_customize_header_toolbar(){
+// select_message_in_folder(0);
+//
+// // It is necessary to press the Get Message Button to get the popup menu populated
+// mc.click(mc.aid("button-getmsg", {class: "toolbarbutton-menubutton-dropmarker"}));
+// mc.ewait("button-getAllNewMsgSeparator");
+//
+// var getMailButtonPopup = mc.eid("button-getMsgPopup").node;
+// var originalServerCount = getMailButtonPopup.childElementCount;
+//
+// // Open customization dialog, because it broke the Get Message Button popup menu
+// // see https://bugzilla.mozilla.org/show_bug.cgi?id=565045
+// let ctc = open_header_pane_toolbar_customization(mc);
+// close_header_pane_toolbar_customization(ctc);
+//
+// // Press the Get Message Button to populate popup menu again
+// mc.click(mc.aid("button-getmsg", {class: "toolbarbutton-menubutton-dropmarker"}));
+// mc.ewait("button-getAllNewMsgSeparator");
+//
+// getMailButtonPopup = mc.eid("button-getMsgPopup").node;
+// var finalServerCount = getMailButtonPopup.childElementCount;
+//
+// if (originalServerCount != finalServerCount) {
+// throw new Error("number of entries in Get Message Button popup menu after " +
+// "header toolbar customization " +
+// finalServerCount + " <> as before: " +
+// originalServerCount);
+// }
+//}
+
+/**
+ * Test header pane toolbar customization: Check for default button sets
+ */
+function test_customize_header_toolbar_check_default()
+{
+ let curMessage = select_message_in_folder(0);
+ let hdrToolbar = mc.eid("header-view-toolbar").node;
+ let hdrBarDefaultSet = hdrToolbar.getAttribute("defaultset");
+ assert_equals(hdrToolbar.currentSet, hdrBarDefaultSet);
+ // In a fresh profile the currentset attribute does not
+ // exist, i.e. it returns empty. So check for both valid
+ // posiblities.
+ assert_true((hdrToolbar.getAttribute("currentset") == "") ||
+ (hdrToolbar.getAttribute("currentset") == hdrBarDefaultSet),
+ "Header Toolbar currentset should be empty or contain default buttons "+
+ "but contains: " + hdrToolbar.getAttribute("currentset"));
+ // Now make sure, that also the attribute gets set:
+ restore_and_check_default_buttons(mc);
+
+ // Display message in new window and check that the default
+ // buttons are shown there.
+ let msgc = open_selected_message_in_new_window();
+ assert_selected_and_displayed(msgc, curMessage);
+ let hdrToolbar = msgc.eid("header-view-toolbar").node;
+ let hdrBarDefaultSet = hdrToolbar.getAttribute("defaultset");
+ assert_equals(hdrToolbar.currentSet, hdrBarDefaultSet);
+ // In a fresh profile the currentset attribute does not
+ // exist, i.e. it returns empty. So check for both valid
+ // posiblities.
+ assert_true((hdrToolbar.getAttribute("currentset") == "") ||
+ (hdrToolbar.getAttribute("currentset") == hdrBarDefaultSet),
+ "Header Toolbar currentset should be empty or contain default buttons "+
+ "but contains: " + hdrToolbar.getAttribute("currentset"));
+ // Now make sure, that also the attribute gets set:
+ restore_and_check_default_buttons(msgc);
+
+ close_window(msgc);
+}
+
+///**
+// * Test header pane toolbar customization: Reorder buttons
+// */
+function test_customize_header_toolbar_reorder_buttons()
+{
+ let curMessage = select_message_in_folder(0);
+
+ // Restore the default buttons to get defined starting conditions.
+ restore_and_check_default_buttons(mc);
+
+ // Save the currentSet of the toolbar before opening the
+ // customization dialog, to get out of the way of the
+ // wrapper- prefix.
+ let toolbar = mc.eid("header-view-toolbar").node;
+ let oldSet = filterInvisibleButtons(mc, toolbar.currentSet).split(",");
+
+ let ctc = open_header_pane_toolbar_customization(mc);
+ let currentSet = filterInvisibleButtons(mc, toolbar.currentSet).split(",");
+
+ for (let i=1; i<currentSet.length; i++) {
+ let button1 = mc.e(currentSet[i]);
+ let button2 = mc.e(currentSet[i-1]);
+ // Move each button to the left of its left neighbour starting with
+ // the second button, i.e. reverse the order of the buttons.
+ drag_n_drop_element(button1, mc.window, button2, mc.window, 0.25, 0.0, toolbar);
+ }
+ close_header_pane_toolbar_customization(ctc);
+
+ // Check, if the toolbar is really in reverse order of beginning.
+ let reverseSet = oldSet.reverse().join(",");
+ assert_equals(filterInvisibleButtons(mc, toolbar.currentSet), reverseSet);
+ assert_equals(filterInvisibleButtons(mc, toolbar.getAttribute("currentset")),
+ reverseSet);
+
+ // Display message in new window and check that the default
+ // buttons are shown there.
+ let msgc = open_selected_message_in_new_window();
+ assert_selected_and_displayed(msgc, curMessage);
+ let hdrToolbar = msgc.eid("header-view-toolbar").node;
+ let hdrBarDefaultSet = hdrToolbar.getAttribute("defaultset");
+ assert_equals(hdrToolbar.currentSet, hdrBarDefaultSet);
+ assert_equals(hdrToolbar.getAttribute("currentset"), hdrBarDefaultSet);
+ close_window(msgc);
+
+ // Leave the toolbar in the default state.
+ restore_and_check_default_buttons(mc);
+}
+//
+///**
+// * Test header pane toolbar customization: Change buttons in
+// * separate mail window
+// */
+function test_customize_header_toolbar_separate_window()
+{
+ let curMessage = select_message_in_folder(0);
+
+ // Restore the default buttons to get defined starting conditions.
+ restore_and_check_default_buttons(mc);
+
+ // Display message in new window and check that the default
+ // buttons are shown there.
+ let msgc = open_selected_message_in_new_window();
+ assert_selected_and_displayed(msgc, curMessage);
+ let hdrToolbar = msgc.eid("header-view-toolbar").node;
+ let hdrBarDefaultSet = hdrToolbar.getAttribute("defaultset");
+ assert_equals(hdrToolbar.currentSet, hdrBarDefaultSet);
+ assert_equals(hdrToolbar.getAttribute("currentset"), hdrBarDefaultSet);
+
+ // Save the currentSet of the toolbar before opening the
+ // customization dialog, to get out of the way of the
+ // wrapper- prefix.
+ let toolbar = msgc.eid("header-view-toolbar").node;
+ let oldSet = filterInvisibleButtons(msgc, toolbar.currentSet).split(",");
+
+ let ctc = open_header_pane_toolbar_customization(msgc);
+ let currentSet = filterInvisibleButtons(msgc, toolbar.currentSet).split(",");
+ for (let i=1; i<currentSet.length; i++) {
+ let button1 = msgc.e(currentSet[i]);
+ let button2 = msgc.e(currentSet[i-1]);
+ // Move each button to the left of its left neighbour starting with
+ // the second button, i.e. reverse the order of the buttons.
+ drag_n_drop_element(button1, msgc.window, button2, msgc.window, 0.25, 0.0, toolbar);
+ }
+ close_header_pane_toolbar_customization(ctc);
+
+ // Check, if the toolbar is really in reverse order of beginning.
+ let reverseSet = oldSet.reverse().join(",");
+ assert_equals(filterInvisibleButtons(msgc, toolbar.currentSet), reverseSet);
+ assert_equals(filterInvisibleButtons(msgc, toolbar.getAttribute("currentset")),
+ reverseSet);
+
+ // Make sure we have a different window open, so that we don't start shutting
+ // down just because the last window was closed
+ let abwc = openAddressBook();
+ // The 3pane window is closed and opened again.
+ close3PaneWindow();
+ close_window(msgc);
+
+ mc = open3PaneWindow();
+ abwc.window.close();
+ select_message_in_folder(0);
+
+ // Check, if the buttons in the mail3pane window are the correct ones.
+ let hdrToolbar = mc.eid("header-view-toolbar").node;
+ let hdrBarDefaultSet = hdrToolbar.getAttribute("defaultset");
+ assert_equals(hdrToolbar.currentSet, hdrBarDefaultSet);
+ assert_equals(hdrToolbar.getAttribute("currentset"), hdrBarDefaultSet);
+
+ // Open separate mail window again and check another time.
+ let msgc = open_selected_message_in_new_window();
+ assert_selected_and_displayed(msgc, curMessage);
+ let toolbar = msgc.eid("header-view-toolbar").node;
+ assert_equals(filterInvisibleButtons(msgc, toolbar.currentSet), reverseSet);
+ assert_equals(filterInvisibleButtons(msgc, toolbar.getAttribute("currentset")),
+ reverseSet);
+
+ // Leave the toolbar in the default state.
+ restore_and_check_default_buttons(msgc);
+ close_window(msgc);
+}
+
+/**
+ * Test header pane toolbar customization: Remove buttons
+ */
+function test_customize_header_toolbar_remove_buttons(){
+ // Save currentset of toolbar for adding the buttons back
+ // at the end.
+ var lCurrentset;
+
+ select_message_in_folder(0);
+
+ // Restore the default buttons to get defined starting conditions.
+ restore_and_check_default_buttons(mc);
+
+ let ctc = open_header_pane_toolbar_customization(mc);
+ let toolbar = mc.eid("header-view-toolbar").node;
+ lCurrentset = filterInvisibleButtons(mc, toolbar.currentSet).split(",");
+ let target = ctc.e("palette-box");
+ for (let i=0; i<lCurrentset.length; i++) {
+ let button = mc.e(lCurrentset[i]);
+ drag_n_drop_element(button, mc.window, target, ctc.window, 0.5, 0.5, toolbar);
+ }
+ close_header_pane_toolbar_customization(ctc);
+
+ // Check, if the toolbar is really empty.
+ let toolbar = mc.eid("header-view-toolbar").node;
+ assert_equals(filterInvisibleButtons(mc, toolbar.currentSet), "__empty");
+ assert_equals(filterInvisibleButtons(mc, toolbar.getAttribute("currentset")),
+ "__empty");
+
+ // Move to the next message and check again.
+ let curMessage = select_message_in_folder(1);
+ assert_equals(filterInvisibleButtons(mc, toolbar.currentSet), "__empty");
+ assert_equals(filterInvisibleButtons(mc, toolbar.getAttribute("currentset")),
+ "__empty");
+
+ // Display message in new window and check that the default
+ // buttons are shown there.
+ let msgc = open_selected_message_in_new_window();
+ assert_selected_and_displayed(msgc, curMessage);
+ let hdrToolbar = msgc.eid("header-view-toolbar").node;
+ let hdrBarDefaultSet = hdrToolbar.getAttribute("defaultset");
+ assert_equals(hdrToolbar.currentSet, hdrBarDefaultSet);
+ assert_equals(hdrToolbar.getAttribute("currentset"), hdrBarDefaultSet);
+ close_window(msgc);
+
+ // Check the persistency of the buttons.
+
+ // Make sure we have a different window open, so that we don't start shutting
+ // down just because the last window was closed
+ let abwc = openAddressBook();
+ // The 3pane window is closed.
+ close3PaneWindow();
+ mc = open3PaneWindow();
+ abwc.window.close();
+ select_message_in_folder(0);
+
+ let toolbar = mc.eid("header-view-toolbar").node;
+ assert_equals(filterInvisibleButtons(mc, toolbar.currentSet), "__empty");
+ assert_equals(filterInvisibleButtons(mc, toolbar.getAttribute("currentset")),
+ "__empty");
+
+ // Check that all removed buttons show up in the palette
+ // and move it back in the toolbar.
+ let ctc = open_header_pane_toolbar_customization(mc);
+ let toolbar = mc.eid("header-view-toolbar").node;
+ let palette = ctc.e("palette-box");
+ for (let i=0; i<lCurrentset.length; i++) {
+ let button = ctc.e(lCurrentset[i]);
+ assert_true(button!=null, "Button " + lCurrentset[i] + " not in palette");
+ // Drop each button to the right end of the toolbar, so we should get the
+ // original order.
+ drag_n_drop_element(button, ctc.window, toolbar, mc.window, 0.99, 0.5, palette);
+ }
+ close_header_pane_toolbar_customization(ctc);
+
+ let toolbar = mc.eid("header-view-toolbar").node;
+ assert_equals(filterInvisibleButtons(mc, toolbar.currentSet),
+ filterInvisibleButtons(mc, hdrBarDefaultSet));
+ assert_equals(filterInvisibleButtons(mc, toolbar.getAttribute("currentset")),
+ filterInvisibleButtons(mc, hdrBarDefaultSet));
+}
+
+/**
+ * Test header pane toolbar customization dialog layout
+ */
+function test_customize_header_toolbar_dialog_style(){
+ select_message_in_folder(0);
+
+ // Restore the default buttons to get defined starting conditions.
+ restore_and_check_default_buttons(mc);
+
+ let ctc = open_header_pane_toolbar_customization(mc);
+
+ // The full mode menulist entry is hidden, because in the header toolbar
+ // this mode is disabled.
+ let fullMode = ctc.window.document.getElementById("main-box").
+ querySelector("[value='full']");
+ assert_equals(ctc.window.getComputedStyle(fullMode).getPropertyValue("display"), "none");
+ // The icon menulist entry is selected, because in the header toolbar with CompactHeader installed
+ // this is the default mode.
+ let iconMode = ctc.window.document.getElementById("modelist").
+ querySelector("[value='icons']");
+ assert_equals(iconMode.getAttribute("selected"), "true");
+
+ // The small icons checkbox is hidden, because in the header toolbar
+ // this mode is the only possible (therefore, the checked attribute is true).
+ let smallIcons = ctc.eid("smallicons").node;
+ assert_equals(smallIcons.getAttribute("checked"), "true");
+ assert_equals(ctc.window.getComputedStyle(smallIcons).getPropertyValue("display"), "none");
+
+ // The add new toolbar button is hidden, because in the header toolbar
+ // this functionality is not available.
+ let addNewToolbar = ctc.window.document.getElementById("main-box").
+ querySelector("[oncommand='addNewToolbar();']");
+ assert_equals(ctc.window.getComputedStyle(addNewToolbar).getPropertyValue("display"), "none");
+
+ close_header_pane_toolbar_customization(ctc);
+}
+
+/**
+ * Test header pane toolbar customization dialog for button style changes
+ */
+function test_customize_header_toolbar_change_button_style(){
+ select_message_in_folder(0);
+
+ // Restore the default buttons to get defined starting conditions.
+ restore_and_check_default_buttons(mc);
+ // The default mode is icon visible only.
+ subtest_buttons_style("-moz-box", "none");
+
+ // Change the button style to text and icon mode
+ let ctc = open_header_pane_toolbar_customization(mc);
+ let iconMode = ctc.window.document.getElementById("main-box").
+ querySelector("[value='textbesideicon']");
+ ctc.click(new elib.Elem(iconMode));
+ close_header_pane_toolbar_customization(ctc);
+
+ subtest_buttons_style("-moz-box", "-moz-box");
+
+ // Change the button style to icon mode only
+ let ctc = open_header_pane_toolbar_customization(mc);
+ let iconMode = ctc.window.document.getElementById("main-box").
+ querySelector("[value='icons']");
+ ctc.click(new elib.Elem(iconMode));
+ close_header_pane_toolbar_customization(ctc);
+
+ subtest_buttons_style("-moz-box", "none");
+
+ // Change the button style to text (only) mode
+ let ctc = open_header_pane_toolbar_customization(mc);
+ let textMode = ctc.window.document.getElementById("main-box").
+ querySelector("[value='text']");
+ ctc.click(new elib.Elem(textMode));
+ close_header_pane_toolbar_customization(ctc);
+
+ subtest_buttons_style("none", "-moz-box");
+
+ // The default mode is icon visible only.
+ restore_and_check_default_buttons(mc);
+ subtest_buttons_style("-moz-box", "none");
+}
+
+/**
+ * Select message in current (global) folder.
+ */
+function select_message_in_folder(aMessageNum)
+{
+ be_in_folder(folder);
+
+ // select and open the first message
+ let curMessage = select_click_row(aMessageNum);
+
+ // make sure it loads
+ wait_for_message_display_completion(mc);
+ assert_selected_and_displayed(mc, curMessage);
+
+ return curMessage;
+}
+
+/**
+ * Check all buttons in the toolbar for the correct style
+ * of text and icon.
+ */
+function subtest_buttons_style(aIconVisibility, aLabelVisibility)
+{
+ let toolbar = mc.eid("header-view-toolbar").node;
+ let currentSet = filterInvisibleButtons(mc, toolbar.currentSet).split(",");
+
+ for (let i=0; i<currentSet.length; i++) {
+ // XXX For the moment only consider normal toolbar buttons.
+ // XXX Handling of toolbaritem buttons has to be added later,
+ // XXX especially the smart reply button!
+ if (mc.eid(currentSet[i]).node.tagName == "toolbarbutton") {
+ let icon = mc.aid(currentSet[i], {class: "toolbarbutton-icon"}).node;
+ let label = mc.aid(currentSet[i], {class: "toolbarbutton-text"}).node;
+ assert_equals(mc.window.getComputedStyle(icon).getPropertyValue("display"), aIconVisibility);
+ assert_equals(mc.window.getComputedStyle(label).getPropertyValue("display"), aLabelVisibility);
+ }
+ }
+}
+
+/**
+ * Restore the default buttons in the header pane toolbar
+ * by clicking the corresponding button in the palette dialog
+ * and check if it worked.
+ */
+function restore_and_check_default_buttons(aController)
+{
+ let ctc = open_header_pane_toolbar_customization(aController);
+ let restoreButton = ctc.window.document.getElementById("main-box").
+ querySelector("[oncommand='overlayRestoreDefaultSet();']");
+ ctc.click(new elib.Elem(restoreButton));
+ close_header_pane_toolbar_customization(ctc);
+
+ let hdrToolbar = aController.eid("header-view-toolbar").node;
+ let hdrBarDefaultSet = hdrToolbar.getAttribute("defaultset");
+
+ assert_equals(hdrToolbar.currentSet, hdrBarDefaultSet);
+ assert_equals(hdrToolbar.getAttribute("currentset"), hdrBarDefaultSet);
+}
+
+/*
+ * Open the header pane toolbar customization dialog.
+ */
+function open_header_pane_toolbar_customization(aController)
+{
+ let ctc;
+ aController.click(aController.eid("CustomizeHeaderToolbar"));
+ // Depending on preferences the customization dialog is
+ // either a normal window or embedded into a sheet.
+ if (prefBranch.getBoolPref(PREF, true)) {
+ aController.ewait("donebutton");
+ let contentWindow = aController.eid("customizeToolbarSheetIFrame").node.contentWindow;
+ ctc = WindowHelper.augment_controller(new controller.MozMillController(contentWindow));
+ }
+ else {
+ ctc = WindowHelper.wait_for_existing_window("mail:customizetoolbar");
+ }
+ return ctc;
+}
+
+/*
+ * Close the header pane toolbar customization dialog.
+ */
+function close_header_pane_toolbar_customization(aCtc)
+{
+ aCtc.click(aCtc.eid("donebutton"));
+ // XXX There should be an equivalent for testing the closure of
+ // XXX the dialog embedded in a sheet, but I do not know how.
+ if (!prefBranch.getBoolPref(PREF, true)) {
+ assert_true(aCtc.window.closed, "The customization dialog is not closed.");
+ }
+}
+
+/**
+ * Helper function to open an extra window, so that the 3pane
+ * window can be closed and opend again for persistancy checks.
+ * They are copied from the test-session-store.js.
+ */
+function close3PaneWindow() {
+ let windowMediator = Cc["@mozilla.org/appshell/window-mediator;1"].
+ getService(Ci.nsIWindowMediator);
+ let mail3PaneWindow = windowMediator.getMostRecentWindow("mail:3pane");
+ // close the 3pane window
+ mail3PaneWindow.close();
+}
+
+function open3PaneWindow() {
+ let windowWatcher = Cc["@mozilla.org/embedcomp/window-watcher;1"].
+ getService(Ci.nsIWindowWatcher);
+ WindowHelper.plan_for_new_window("mail:3pane");
+ windowWatcher.openWindow(null,
+ "chrome://messenger/content/messenger.xul", "",
+ "all,chrome,dialog=no,status,toolbar",
+ null);
+ return WindowHelper.wait_for_new_window("mail:3pane");
+}
+
+function openAddressBook() {
+ let windowWatcher = Cc["@mozilla.org/embedcomp/window-watcher;1"].
+ getService(Ci.nsIWindowWatcher);
+ WindowHelper.plan_for_new_window("mail:addressbook");
+ windowWatcher.openWindow(
+ null,
+ "chrome://messenger/content/addressbook/addressbook.xul", "",
+ "all,chrome,dialog=no,status,toolbar",
+ null);
+ return WindowHelper.wait_for_new_window("mail:addressbook");
+}
+
+/*
+ * Remove invsible buttons from (comma separated) buttons list
+ */
+function filterInvisibleButtons(aController, aButtons) {
+ let buttons = aButtons.split(",");
+ let result = new Array;
+
+ for (let i=1; i<buttons.length; i++) {
+ button = buttons[i].replace(new RegExp("wrapper-"), "");
+ if ((aController.eid(button).node) &&
+ (!aController.eid(button).node.getAttribute("collapsed"))
+ ) {
+ result.push(buttons[i]);
+ }
+ }
+
+ let strResult;
+ if (result.length > 0) {
+ strResult = result.join(",");
+ }
+ else {
+ strResult = "__empty";
+ }
+
+ return strResult;
+}
diff --git a/test/compactheader/test-message-header.js b/test/compactheader/test-message-header.js
new file mode 100644
index 0000000..94950c3
--- /dev/null
+++ b/test/compactheader/test-message-header.js
@@ -0,0 +1,837 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Thunderbird Mail Client.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Blake Winton <bwinton at latte.ca>
+ * Dan Mosedale <dmose at mozillamessaging.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Test that we can add a tag to a message without messing up the header.
+ */
+var MODULE_NAME = 'test-message-header';
+
+var RELATIVE_ROOT = '../shared-modules';
+var MODULE_REQUIRES = ['folder-display-helpers', 'window-helpers',
+ 'address-book-helpers'];
+
+var elib = {};
+Cu.import('resource://mozmill/modules/elementslib.js', elib);
+
+var folder;
+
+function setupModule(module) {
+ let fdh = collector.getModule('folder-display-helpers');
+ fdh.installInto(module);
+ let wh = collector.getModule('window-helpers');
+ wh.installInto(module);
+ let abh = collector.getModule('address-book-helpers');
+ abh.installInto(module);
+
+ folder = create_folder("MessageWindowA");
+
+ // create a message that has the interesting headers that commonly
+ // show up in the message header pane for testing
+ let msg = create_message({cc: msgGen.makeNamesAndAddresses(20), // YYY
+ subject: "This is a really, really, really, really, really, really, really, really, long subject.",
+ clobberHeaders: {
+ "Newsgroups": "alt.test",
+ "Reply-To": "J. Doe <j.doe at momo.invalid>",
+ "Content-Base": "http://example.com/",
+ "Bcc": "Richard Roe <richard.roe at momo.invalid>"
+ }});
+
+ add_message_to_folder(folder, msg);
+
+ // create a message that has boring headers to be able to switch to and
+ // back from, to force the more button to collapse again.
+ msg = create_message();
+ add_message_to_folder(folder, msg);
+}
+
+function test_add_tag_with_really_long_label() {
+ be_in_folder(folder);
+
+ // select the first message, which will display it
+ let curMessage = select_click_row(0);
+
+ assert_selected_and_displayed(mc, curMessage);
+
+ let topColumn = mc.eid("expandedHeadersNameColumn").node;
+ let bottomColumn = mc.eid("expandedHeaders2NameColumn").node;
+
+ if (topColumn.clientWidth != bottomColumn.clientWidth)
+ throw new Error("Header columns have different widths! " +
+ topColumn.clientWidth + " != " + bottomColumn.clientWidth);
+ let defaultWidth = topColumn.clientWidth;
+
+ // Make the tags label really long.
+ let tagsLabel = mc.eid("expandedtagsLabel").node;
+ let oldTagsValue = tagsLabel.value;
+ tagsLabel.value = "taaaaaaaaaaaaaaaaaags";
+
+ if (topColumn.clientWidth != bottomColumn.clientWidth) {
+ tagsLabel.value = oldTagsValue;
+ throw new Error("Header columns have different widths! " +
+ topColumn.clientWidth + " != " + bottomColumn.clientWidth);
+ }
+ if (topColumn.clientWidth != defaultWidth) {
+ tagsLabel.value = oldTagsValue;
+ throw new Error("Header columns changed width! " +
+ topColumn.clientWidth + " != " + defaultWidth);
+ }
+
+ // Add the first tag, and make sure that the label are the same length.
+ mc.keypress(mc.eid("expandedHeadersNameColumn"), "1", {});
+
+ if (topColumn.clientWidth != bottomColumn.clientWidth) {
+ tagsLabel.value = oldTagsValue;
+ throw new Error("Header columns have different widths! " +
+ topColumn.clientWidth + " != " + bottomColumn.clientWidth);
+ }
+ if (topColumn.clientWidth == defaultWidth) {
+ tagsLabel.value = oldTagsValue;
+ throw new Error("Header columns didn't change width! " +
+ topColumn.clientWidth + " == " + defaultWidth);
+ }
+
+ // Remove the tag and put it back so that the a11y label gets regenerated
+ // with the normal value rather than "taaaaaaaags"
+ tagsLabel.value = oldTagsValue;
+ mc.keypress(mc.eid("expandedHeadersNameColumn"), "1", {});
+ mc.keypress(mc.eid("expandedHeadersNameColumn"), "1", {});
+}
+
+/**
+ * @param headerName used for pretty-printing in exceptions
+ * @param headerValueElement code to be eval()ed returning the DOM element
+ * with the data.
+ * @param expectedName code to be eval()ed returning the expected value of
+ * nsIAccessible.name for the DOM element in question
+ * @param expectedRole the expected value for nsIAccessible.role
+ */
+let headersToTest = [
+{
+ headerName: "Subject",
+ headerValueElement: "mc.a('expandedsubjectBox', {class: 'headerValue'})",
+ expectedName: "mc.e('expandedsubjectLabel').value.slice(0,-1) + ': ' + " +
+ "headerValueElement.textContent",
+ expectedRole: Ci.nsIAccessibleRole.ROLE_ENTRY
+},
+{
+ headerName: "Content-Base",
+ headerValueElement: "mc.a('expandedcontent-baseBox', {class: 'headerValue text-link headerValueUrl'})",
+ expectedName: "mc.e('expandedcontent-baseLabel').value.slice(0,-1) + ': ' + " +
+ "headerValueElement.textContent",
+ expectedRole: Ci.nsIAccessibleRole.ROLE_ENTRY
+},
+{
+ headerName: "From",
+ headerValueElement: "mc.window.document.getAnonymousElementByAttribute(" +
+ "mc.a('expandedfromBox', {tagName: 'mail-emailaddress'})," +
+ "'class', 'emailDisplayButton')",
+ expectedName: "mc.e('expandedfromLabel').value.slice(0,-1) + ': ' + " +
+ "headerValueElement.parentNode.getAttribute('fullAddress')",
+ expectedRole: Ci.nsIAccessibleRole.ROLE_ENTRY
+},
+{
+ headerName: "To",
+ headerValueElement: "mc.window.document.getAnonymousElementByAttribute(" +
+ "mc.a('expandedtoBox', {tagName: 'mail-emailaddress'})," +
+ "'class', 'emailDisplayButton')",
+ expectedName: "mc.e('expandedtoLabel').value.slice(0,-1) + ': ' + " +
+ "headerValueElement.parentNode.getAttribute('fullAddress')",
+ expectedRole: Ci.nsIAccessibleRole.ROLE_ENTRY
+},
+{
+ headerName: "Cc",
+ headerValueElement: "mc.window.document.getAnonymousElementByAttribute(" +
+ "mc.a('expandedccBox', {tagName: 'mail-emailaddress'})," +
+ "'class', 'emailDisplayButton')",
+ expectedName: "mc.e('expandedccLabel').value.slice(0,-1) + ': ' + " +
+ "headerValueElement.parentNode.getAttribute('fullAddress')",
+ expectedRole: Ci.nsIAccessibleRole.ROLE_ENTRY
+},
+{
+ headerName: "Bcc",
+ headerValueElement: "mc.window.document.getAnonymousElementByAttribute(" +
+ "mc.a('expandedbccBox', {tagName: 'mail-emailaddress'})," +
+ "'class', 'emailDisplayButton')",
+ expectedName: "mc.e('expandedbccLabel').value.slice(0,-1) + ': ' + " +
+ "headerValueElement.parentNode.getAttribute('fullAddress')",
+ expectedRole: Ci.nsIAccessibleRole.ROLE_ENTRY
+},
+{
+ headerName: "Reply-To",
+ headerValueElement: "mc.window.document.getAnonymousElementByAttribute(" +
+ "mc.a('expandedreply-toBox', {tagName: 'mail-emailaddress'})," +
+ "'class', 'emailDisplayButton')",
+ expectedName: "mc.e('expandedreply-toLabel').value.slice(0,-1) + ': ' + " +
+ "headerValueElement.parentNode.getAttribute('fullAddress')",
+ expectedRole: Ci.nsIAccessibleRole.ROLE_ENTRY
+},
+{
+ headerName: "Newsgroups",
+ headerValueElement: "mc.window.document.getAnonymousElementByAttribute(" +
+ "mc.a('expandednewsgroupsBox', {tagName: 'mail-newsgroup'})," +
+ "'class', 'newsgrouplabel')",
+ expectedName: "mc.e('expandednewsgroupsLabel').value.slice(0,-1) + ': ' + " +
+ "headerValueElement.parentNode.parentNode.getAttribute('newsgroup')",
+ expectedRole: Ci.nsIAccessibleRole.ROLE_ENTRY
+},
+{
+ headerName: "Tags",
+ headerValueElement: "mc.a('expandedtagsBox', {class: 'tagvalue blc-FF0000'})",
+ expectedName: "mc.e('expandedtagsLabel').value.slice(0,-1) + ': ' + " +
+ "headerValueElement.getAttribute('value')",
+ expectedRole: Ci.nsIAccessibleRole.ROLE_LABEL
+}
+];
+
+// used to get the accessible object for a DOM node
+let gAccRetrieval = Cc["@mozilla.org/accessibleRetrieval;1"].
+ getService(Ci.nsIAccessibleRetrieval);
+
+/**
+ * Use the information from aHeaderInfo to verify that screenreaders will
+ * do the right thing with the given message header.
+ *
+ * @param {Object} aHeaderInfo Information about how to do the verification;
+ * See the comments above the headersToTest array
+ * for details.
+ */
+function verify_header_a11y(aHeaderInfo) {
+ // XXX Don't use eval here.
+ let headerValueElement = eval(aHeaderInfo.headerValueElement);
+
+ let headerAccessible = gAccRetrieval.getAccessibleFor(headerValueElement);
+ if (headerAccessible.role != aHeaderInfo.expectedRole) {
+ throw new Error("role for " + aHeaderInfo.headerName + " was " +
+ headerAccessible.role + "; should have been " +
+ aHeaderInfo.expectedRole);
+ }
+
+ // XXX Don't use eval here.
+ let expectedName = eval(aHeaderInfo.expectedName);
+ if (headerAccessible.name != expectedName) {
+ throw new Error("headerAccessible.name for " + aHeaderInfo.headerName +
+ " was '" + headerAccessible.name + "'; expected '" +
+ expectedName + "'");
+ }
+}
+
+/**
+ * Test the accessibility attributes of the various message headers.
+ *
+ * XXX This test used to be after test_more_button_with_many_recipients,
+ * however, there were some accessibility changes that it didn't seem to play
+ * nicely with, and the toggling of the "more" button on the cc field was
+ * causing this test to fail on the cc element. Tests with accessibilty
+ * hardware/software showed that the code was working fine. Therefore the test
+ * may be suspect.
+ */
+function test_a11y_attrs() {
+ // skip this test on platforms that don't support accessibility
+ if (!("nsIAccessibleRole" in Components.interfaces))
+ return;
+
+ be_in_folder(folder);
+
+ // select and open the first message
+ let curMessage = select_click_row(0);
+
+ // make sure it loads
+ wait_for_message_display_completion(mc);
+ assert_selected_and_displayed(mc, curMessage);
+
+ headersToTest.forEach(verify_header_a11y);
+}
+
+function test_more_button_with_many_recipients()
+{
+ // Start on the interesting message.
+ let curMessage = select_click_row(0);
+
+ // make sure it loads
+ wait_for_message_display_completion(mc);
+ assert_selected_and_displayed(mc, curMessage);
+
+ // Check the mode of the header.
+ let headerBox = mc.eid("expandedHeaderView");
+ let previousHeaderMode = headerBox.node.getAttribute("show_header_mode");
+
+ // Click the "more" button.
+ let moreIndicator = mc.eid("expandedccBox");
+ moreIndicator = mc.window.document.getAnonymousElementByAttribute(
+ moreIndicator.node, "anonid", "more");
+ moreIndicator = new elementslib.Elem(moreIndicator);
+ mc.click(moreIndicator);
+
+ // Check the new mode of the header.
+ if (headerBox.node.getAttribute("show_header_mode") != "all")
+ throw new Error("Header Mode didn't change to 'all'! " + "old=" +
+ previousHeaderMode + ", new=" +
+ headerBox.node.getAttribute("show_header_mode"));
+
+ // Switch to the boring message, to force the more button to collapse.
+ curMessage = select_click_row(1);
+
+ // make sure it loads
+ wait_for_message_display_completion(mc);
+ assert_selected_and_displayed(mc, curMessage);
+
+ // Check the even newer mode of the header.
+ if (headerBox.node.getAttribute("show_header_mode") != previousHeaderMode)
+ throw new Error("Header Mode changed from " + previousHeaderMode +
+ " to " + headerBox.node.getAttribute("show_header_mode") +
+ " and didn't change back.");
+}
+
+/**
+ * Test that we can open up the inline contact editor when we
+ * click on the star.
+ */
+function test_clicking_star_opens_inline_contact_editor()
+{
+ // Make sure we're in the right folder
+ be_in_folder(folder);
+
+ // Add a new message
+ let msg = create_message();
+ add_message_to_folder(folder, msg);
+
+ // Open the latest message
+ let curMessage = select_click_row(-1);
+ // Make sure the star is clicked, and we add the
+ // new contact to our address book
+ let toDescription = mc.a('expandedtoBox', {class: "headerValue"});
+
+ // Ensure that the inline contact editing panel is not open
+ let contactPanel = mc.eid('editContactPanel').getNode();
+ assert_not_equals(contactPanel.state, "open");
+ subtest_more_widget_star_click(toDescription);
+
+ // Ok, if we're here, then the star has been clicked, and
+ // the contact has been added to our AB.
+ let addrs = toDescription.getElementsByTagName('mail-emailaddress');
+ let lastAddr = addrs[addrs.length-1];
+
+ // Click on the star, and ensure that the inline contact
+ // editing panel opens
+ mc.click(mc.aid(lastAddr, {class: 'emailStar'}));
+ assert_equals(contactPanel.state, "open");
+ contactPanel.hidePopup();
+}
+
+/**
+ * Test that if a contact belongs to a mailing list within their
+ * address book, then the inline contact editor will not allow
+ * the user to change what address book the contact belongs to.
+ * The editor should also show a message to explain why the
+ * contact cannot be moved.
+ */
+function test_address_book_switch_disabled_on_contact_in_mailing_list()
+{
+ const MAILING_LIST_DIRNAME = "Some Mailing List";
+ const ADDRESS_BOOK_NAME = "Some Address Book";
+ // Add a new message
+ let msg = create_message();
+ add_message_to_folder(folder, msg);
+
+ // Make sure we're in the right folder
+ be_in_folder(folder);
+
+ // Open the latest message
+ let curMessage = select_click_row(-1);
+
+ // Make sure the star is clicked, and we add the
+ // new contact to our address book
+ let toDescription = mc.a('expandedtoBox', {class: "headerValue"});
+
+ // Ensure that the inline contact editing panel is not open
+ let contactPanel = mc.eid('editContactPanel').getNode();
+ assert_not_equals(contactPanel.state, "open");
+
+ subtest_more_widget_star_click(toDescription);
+
+ // Ok, if we're here, then the star has been clicked, and
+ // the contact has been added to our AB.
+ let addrs = toDescription.getElementsByTagName('mail-emailaddress');
+ let lastAddr = addrs[addrs.length-1];
+
+ // Click on the star, and ensure that the inline contact
+ // editing panel opens
+ mc.click(mc.aid(lastAddr, {class: 'emailStar'}));
+ assert_equals(contactPanel.state, "open");
+
+ let abDrop = mc.eid('editContactAddressBookList').getNode();
+ let warningMsg = mc.eid('contactMoveDisabledText').getNode();
+
+ // Ensure that the address book dropdown is not disabled
+ assert_true(!abDrop.disabled);
+ // We should not be displaying any warning
+ assert_true(warningMsg.collapsed);
+
+ // Now close the popup
+ contactPanel.hidePopup();
+
+ // For the contact that was added, create a mailing list in the
+ // address book it resides in, and then add that contact to the
+ // mailing list
+ addrs = toDescription.getElementsByTagName('mail-emailaddress');
+ let targetAddr = addrs[addrs.length-1].getAttribute("emailAddress");
+
+ let cards = get_cards_in_all_address_books_for_email(targetAddr);
+
+ // There should be only one copy of this email address
+ // in the address books.
+ assert_equals(cards.length, 1);
+ let card = cards[0];
+
+ // Remove the card from any of the address books
+ ensure_no_card_exists(targetAddr);
+
+ // Add the card to a new address book, and insert it
+ // into a mailing list under that address book
+ let ab = create_mork_address_book(ADDRESS_BOOK_NAME);
+ ab.dropCard(card, false);
+ let ml = create_mailing_list(MAILING_LIST_DIRNAME);
+ ab.addMailList(ml);
+
+ // Now we have to retrieve the mailing list from
+ // the address book, in order for us to add and
+ // delete cards from it.
+ ml = get_mailing_list_from_address_book(ab, MAILING_LIST_DIRNAME);
+
+ ml.addressLists.appendElement(card, false);
+
+ // Re-open the inline contact editing panel
+ mc.click(mc.aid(lastAddr, {class: 'emailStar'}));
+ assert_equals(contactPanel.state, "open");
+
+ // The dropdown should be disabled now
+ assert_true(abDrop.disabled);
+ // We should be displaying a warning
+ assert_true(!warningMsg.collapsed);
+
+ contactPanel.hidePopup();
+
+ // And if we remove the contact from the mailing list, the
+ // warning should be gone and the address book switching
+ // menu re-enabled.
+
+ let cardArray = Cc["@mozilla.org/array;1"]
+ .createInstance(Ci.nsIMutableArray);
+ cardArray.appendElement(card, false);
+ ml.deleteCards(cardArray);
+
+ // Re-open the inline contact editing panel
+ mc.click(mc.aid(lastAddr, {class: 'emailStar'}));
+ assert_equals(contactPanel.state, "open");
+
+ // Ensure that the address book dropdown is not disabled
+ assert_true(!abDrop.disabled);
+ // We should not be displaying any warning
+ assert_true(warningMsg.collapsed);
+
+ contactPanel.hidePopup();
+}
+
+/**
+ * Test that clicking the adding an address node adds it to the address book.
+ */
+function test_add_contact_from_context_menu() {
+ // Click the contact to show the emailAddressPopup popup menu.
+ mc.click(mc.aid("expandedfromBox", {tagName: "mail-emailaddress"}));
+
+ var addToAddressBookItem = mc.window.document.getElementById("addToAddressBookItem");
+ if (addToAddressBookItem.hidden)
+ throw new Error("addToAddressBookItem is hidden for unknown contact");
+ var editContactItem = mc.window.document.getElementById("editContactItem");
+ if (!editContactItem.getAttribute("hidden"))
+ throw new Error("editContactItem is NOT hidden for unknown contact");
+
+ // Click the Add to Address Book context menu entry.
+ mc.click(mc.eid("addToAddressBookItem"));
+ // (for reasons unknown, the pop-up does not close itself)
+ close_popup(mc, mc.eid("emailAddressPopup"));
+
+ // Now click the contact again, the context menu should now show the
+ // Edit Contact menu instead.
+ mc.click(mc.aid("expandedfromBox", {tagName: "mail-emailaddress"}));
+ // (for reasons unknown, the pop-up does not close itself)
+ close_popup(mc, mc.eid("emailAddressPopup"));
+
+ addToAddressBookItem = mc.window.document.getElementById("addToAddressBookItem");
+ if (!addToAddressBookItem.hidden)
+ throw new Error("addToAddressBookItem is NOT hidden for known contact");
+ editContactItem = mc.window.document.getElementById("editContactItem");
+ if (editContactItem.hidden)
+ throw new Error("editContactItem is hidden for known contact");
+}
+
+function test_that_msg_without_date_clears_previous_headers() {
+ be_in_folder(folder);
+
+ // create a message
+ let msg = create_message();
+
+ // ensure that this message doesn't have a Date header
+ delete msg.headers.Date;
+
+ // this will add the message to the end of the folder
+ add_message_to_folder(folder, msg);
+
+ // select and open the first message
+ let curMessage = select_click_row(0);
+
+ // make sure it loads
+ wait_for_message_display_completion(mc);
+ assert_selected_and_displayed(mc, curMessage);
+
+ // Since we didn't give create_message an argument that would create a
+ // Newsgroups header, the newsgroups <row> element should be collapsed.
+ // However, since the previously displayed message _did_ have such a header,
+ // certain bugs in the display of this header could cause the collapse
+ // never to have happened.
+ if (mc.e("expandednewsgroupsRow").collapsed != true) {
+ throw new Error("Expected <row> elemnent for Newsgroups header to be " +
+ "collapsed, but it wasn't\n!");
+ }
+}
+
+/**
+ * Test various aspects of the (n more) widgetry.
+ */
+function test_more_widget() {
+ // generate message with 35 recips (effectively guarantees overflow for n=3)
+ be_in_folder(folder);
+ let msg = create_message({toCount: 35});
+
+ // add the message to the end of the folder
+ add_message_to_folder(folder, msg);
+
+ // select and open the last message
+ let curMessage = select_click_row(-1);
+
+ // make sure it loads
+ wait_for_message_display_completion(mc);
+ assert_selected_and_displayed(mc, curMessage);
+
+ // get the description element containing the addresses
+ let toDescription = mc.a('expandedtoBox', {class: "headerValue"});
+
+ subtest_more_widget_display(toDescription);
+ subtest_more_widget_click(toDescription);
+ subtest_more_widget_star_click(toDescription);
+}
+
+/**
+ * Test that all addresses are shown in show all header mode
+ */
+function test_show_all_header_mode() {
+ // generate message with 35 recips (effectively guarantees overflow for n=3)
+ be_in_folder(folder);
+ let msg = create_message({toCount: 35});
+
+ // add the message to the end of the folder
+ add_message_to_folder(folder, msg);
+
+ // select and open the last message
+ let curMessage = select_click_row(-1);
+
+ // make sure it loads
+ wait_for_message_display_completion(mc);
+ assert_selected_and_displayed(mc, curMessage);
+
+ // get the description element containing the addresses
+ let toDescription = mc.a('expandedtoBox', {class: "headerValue"});
+
+ change_to_header_normal_mode();
+ subtest_more_widget_display(toDescription);
+ subtest_change_to_all_header_mode(toDescription);
+ change_to_header_normal_mode();
+ subtest_more_widget_click(toDescription);
+}
+
+function change_to_header_normal_mode() {
+ // XXX Clicking on check menu items doesn't work in 1.4.1b1 (bug 474486)...
+ // mc.click(new elib.Elem(mc.menus.View.viewheadersmenu.viewnormalheaders));
+ // ... so call the function instead.
+ mc.window.MsgViewNormalHeaders();
+ mc.sleep(0);
+}
+
+function change_to_all_header_mode() {
+ // XXX Clicking on check menu items doesn't work in 1.4.1b1 (bug 474486)...
+ // mc.click(new elib.Elem(mc.menus.View.viewheadersmenu.viewallheaders));
+ // ... so call the function instead.
+ mc.window.MsgViewAllHeaders();
+ mc.sleep(0);
+}
+
+/**
+ * Get the number of lines in one of the multi-address fields
+ * @param node the description element containing the addresses
+ * @return the number of lines
+ */
+function help_get_num_lines(node) {
+ let style = mc.window.getComputedStyle(node, null);
+ return style.height / style.lineHeight;
+}
+
+/**
+ * Test that the "more" widget displays when it should.
+ * @param toDescription the description node for the "to" field
+ */
+function subtest_more_widget_display(toDescription) {
+ // test that the to element doesn't have more than max lines
+ let numLines = help_get_num_lines(toDescription);
+
+ // get maxline pref
+ let prefBranch = Cc["@mozilla.org/preferences-service;1"]
+ .getService(Ci.nsIPrefService).getBranch(null);
+ let maxLines = prefBranch.getIntPref(
+ "mailnews.headers.show_n_lines_before_more");
+
+ // allow for a 15% tolerance for any padding that may be applied
+ if (numLines < 0.85*maxLines || numLines > 1.15*maxLines) {
+ throw new Error("expected == " + maxLines + "lines; found " + numLines);
+ }
+
+ // test that we've got a (more) node and that it's expanded
+ let moreNode = mc.a('expandedtoBox', {class: 'moreIndicator'});
+ if (!moreNode) {
+ throw new Error("more node not found before activation");
+ }
+ if (moreNode.collapsed) {
+ throw new Error("more node was collapsed when it should have been visible");
+ }
+}
+
+/**
+ * Test that clicking the "more" widget displays all the addresses.
+ * @param toDescription the description node for the "to" field
+ */
+function subtest_more_widget_click(toDescription) {
+ let oldNumLines = help_get_num_lines(toDescription);
+
+ // activate (n more)
+ let moreNode = mc.aid('expandedtoBox', {class: 'moreIndicator'});
+ mc.click(moreNode);
+
+ // test that (n more) is gone
+ moreNode = mc.a('expandedtoBox', {class: 'moreIndicator'});
+ if (!moreNode.collapsed) {
+ throw new Error("more node should be collapsed after activation");
+ }
+
+ // test that we actually have more lines than we did before!
+ let newNumLines = help_get_num_lines(toDescription);
+ if (newNumLines <= oldNumLines) {
+ throw new Error("number of address lines present after more clicked = " +
+ newNumLines + "<= number of lines present beforehand = " + oldNumLines);
+ }
+}
+
+/**
+ * Test that changing to all header lines mode displays all the addresses.
+ * @param toDescription the description node for the "to" field
+ */
+function subtest_change_to_all_header_mode(toDescription) {
+ let oldNumLines = help_get_num_lines(toDescription);
+
+ change_to_all_header_mode();
+ // test that (n more) is gone
+ let moreNode = mc.a('expandedtoBox', {class: 'moreIndicator'});
+ if (!moreNode.collapsed) {
+ throw new Error("more node should be collapsed in all header lines mode");
+ }
+
+ // test that we actually have more lines than we did before!
+ let newNumLines = help_get_num_lines(toDescription);
+ if (newNumLines <= oldNumLines) {
+ throw new Error("number of address lines present in all header lines mode = " +
+ newNumLines + "<= number of lines present beforehand = " + oldNumLines);
+ }
+}
+
+/**
+ * Test that clicking the star updates the UI properly (see bug 563612).
+ * @param toDescription the description node for the "to" field
+ */
+function subtest_more_widget_star_click(toDescription) {
+ let addrs = toDescription.getElementsByTagName('mail-emailaddress');
+ let lastAddr = addrs[addrs.length-1];
+ ensure_no_card_exists(lastAddr.getAttribute("emailAddress"));
+
+ // scroll to the bottom first so the address is in view
+ let view = mc.e('expandedHeaderView');
+ view.scrollTop = view.scrollHeight - view.clientHeight;
+
+ mc.click(mc.aid(lastAddr, {class: 'emailStar'}));
+ if (lastAddr.getAttribute('hascard') == 'false') {
+ throw new Error("address not updated after clicking star");
+ }
+}
+
+/**
+ * Make sure the (more) widget hidden pref actually works with a
+ * non-default value.
+ */
+function test_more_widget_with_maxlines_of_3(){
+
+ // set maxLines to 3
+ let prefBranch = Cc["@mozilla.org/preferences-service;1"]
+ .getService(Ci.nsIPrefService).getBranch(null);
+ let maxLines = prefBranch.setIntPref(
+ "mailnews.headers.show_n_lines_before_more", 3);
+
+ // call test_more_widget again
+ test_more_widget();
+}
+
+/**
+ * Make sure the (more) widget hidden pref also works with an
+ * "all" (0) non-default value.
+ */
+function test_more_widget_with_disabled_more(){
+
+ // set maxLines to 0
+ let prefBranch = Cc["@mozilla.org/preferences-service;1"]
+ .getService(Ci.nsIPrefService).getBranch(null);
+ let maxLines = prefBranch.setIntPref(
+ "mailnews.headers.show_n_lines_before_more", 0);
+
+ // generate message with 35 recips (effectively guarantees overflow for n=3)
+ be_in_folder(folder);
+ let msg = create_message({toCount: 35});
+
+ // add the message to the end of the folder
+ add_message_to_folder(folder, msg);
+
+ // select and open the last message
+ let curMessage = select_click_row(-1);
+
+ // make sure it loads
+ wait_for_message_display_completion(mc);
+ assert_selected_and_displayed(mc, curMessage);
+
+ // test that (n more) is gone
+ let moreNode = mc.a('expandedtoBox', {class: 'moreIndicator'});
+ if (!moreNode.collapsed) {
+ throw new Error("more node should be collapsed in n=0 case");
+ }
+
+ // get the description element containing the addresses
+ let toDescription = mc.a('expandedtoBox', {class: "headerValue"});
+
+ // test that we actually have more lines than the 3 we know are filled
+ let newNumLines = help_get_num_lines(toDescription);
+ if (newNumLines <= 3) {
+ throw new Error("number of address lines present in all addresses mode = " +
+ newNumLines + "<= number of expected minimum of 3 lines filled");
+ }
+}
+
+/**
+ * When the window gets too narrow the toolbar should float above the From
+ * line. Then they need to return back to the right when we get large
+ * enough again.
+ */
+function test_toolbar_collapse_and_expand() {
+ be_in_folder(folder);
+ // Select and open a message, in this case the last, for no particular reason.
+ let curMessage = select_click_row(-1);
+
+ try {
+ let expandedHeadersTopBox = mc.e("expandedHeadersTopBox");
+ let toolbar = mc.e("header-view-toolbar");
+ let mode = toolbar.getAttribute("mode");
+
+ // Get really big, so that we can figure out how big we actually want to be.
+ mc.window.resizeTo(1200, 600);
+ // spin the event loop once
+ mc.sleep(0);
+
+ let folderPaneWidth = mc.e("folderPaneBox").clientWidth;
+ let fromWidth = mc.e("expandedfromRow").clientWidth;
+
+ // This is the biggest we need to be.
+ let bigWidth = folderPaneWidth + fromWidth + toolbar.clientWidth;
+
+ // Now change to icons-only mode for a much smaller toolbar.
+ toolbar.setAttribute("mode", "icons");
+ let smallWidth = folderPaneWidth + fromWidth + toolbar.clientWidth;
+
+ // Re-set the mode to its original value.
+ toolbar.setAttribute("mode", mode);
+
+ // And resize to half way between the big and small widths, so that we
+ // can toggle the mode to force the overflow.
+ mc.window.resizeTo((bigWidth + smallWidth) / 2, 600);
+ // spin the event loop once
+ mc.sleep(0);
+
+ // Make sure we are too small to contain the buttons and from line, so
+ // we will be tall.
+ let tallHeight = expandedHeadersTopBox.clientHeight;
+
+ // Change from icons and text to just icons to make our toolbar
+ // narrower, and by extension our header shorter.
+ toolbar.setAttribute("mode", "icons");
+
+ let shortHeight = expandedHeadersTopBox.clientHeight;
+ if (shortHeight >= tallHeight)
+ throw new Error("The header box should have been made smaller!");
+
+ // Change back to icons and text to make our toolbar wider and our
+ // header taller again.
+ toolbar.setAttribute("mode", mode);
+ if (expandedHeadersTopBox.clientHeight != tallHeight)
+ throw new Error("The header box should have returned to its original size!");
+
+ // And make our window big to achieve the same effect as the just icons mode.
+ mc.window.resizeTo(1200, 600);
+ // spin the event loop once
+ mc.sleep(0);
+ if (expandedHeadersTopBox.clientHeight != shortHeight)
+ throw new Error("The header box should have returned to its wide size!");
+ }
+ finally {
+ // restore window to nominal dimensions; saving was not working out
+ // See also: quick-filter-bar/test-display-issues.js if we change the
+ // default window size.
+ mc.window.resizeTo(1024, 768);
+ }
+}
diff --git a/test/compactheader/test-mouse-event-helpers.js b/test/compactheader/test-mouse-event-helpers.js
new file mode 100644
index 0000000..c46ed51
--- /dev/null
+++ b/test/compactheader/test-mouse-event-helpers.js
@@ -0,0 +1,220 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Thunderbird Mail Client.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Banner <bugzilla at standard8.plus.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var Ci = Components.interfaces;
+var Cc = Components.classes;
+var Cu = Components.utils;
+
+var elib = {};
+Cu.import('resource://mozmill/modules/elementslib.js', elib);
+var mozmill = {};
+Cu.import('resource://mozmill/modules/mozmill.js', mozmill);
+var EventUtils = {};
+Cu.import('resource://mozmill/stdlib/EventUtils.js', EventUtils);
+
+const MODULE_NAME = 'mouse-event-helpers';
+
+
+function setupModule() {
+}
+
+function installInto(module) {
+ setupModule();
+
+ // Now copy helper functions
+ module.drag_n_drop_element = drag_n_drop_element;
+ module.synthesize_drag_start = synthesize_drag_start;
+ module.synthesize_drag_over = synthesize_drag_over;
+ module.synthesize_drag_end = synthesize_drag_end;
+ module.synthesize_drop = synthesize_drop;
+}
+
+/**
+ * Execute a drag and drop session.
+ * @param {XULElement} aDragObject
+ * the element from which the drag session should be started.
+ * @param {} aDragWindow
+ * the window the aDragObject is in
+ * @param {XULElement} aDropObject
+ * the element at which the drag session should be ended.
+ * @param {} aDropWindow
+ * the window the aDropObject is in
+ * @param {} aRelDropX
+ * the relative x-position the element is dropped over the aDropObject
+ * @param {} aRelDropY
+ * the relative y-position the element is dropped over the aDropObject
+ * @param {XULElement} aListener
+ * the element who's drop target should be captured and returned.
+ */
+function drag_n_drop_element(aDragObject, aDragWindow, aDropObject,
+ aDropWindow, aRelDropX, aRelDropY, aListener)
+{
+ let dt = synthesize_drag_start(aDragWindow, aDragObject, aListener);
+
+ // Drop it onto the third tab ...
+ synthesize_drag_over(aDropWindow, aDropObject, dt);
+
+ synthesize_drop(aDropWindow, aDropObject, dt,
+ { screenX : aDropObject.boxObject.screenX +
+ (aDropObject.boxObject.width * aRelDropX),
+ screenY : aDropObject.boxObject.screenY +
+ (aDropObject.boxObject.width * aRelDropY)
+ });
+}
+
+/**
+ * Starts a drag new session.
+ * @param {} aWindow
+ * @param {XULElement} aDispatcher
+ * the element from which the drag session should be started.
+ * @param {XULElement} aListener
+ * the element who's drop target should be captured and returned.
+ * @return {nsIDataTransfer}
+ * returns the DataTransfer Object of captured by aListener.
+ */
+function synthesize_drag_start(aWindow, aDispatcher, aListener)
+{
+ let dt;
+
+ var trapDrag = function(event) {
+
+ if ( !event.dataTransfer )
+ throw "no DataTransfer";
+
+ dt = event.dataTransfer;
+
+ //event.stopPropagation();
+ event.preventDefault();
+ };
+
+ aListener.addEventListener("dragstart", trapDrag, true);
+
+ EventUtils.synthesizeMouse(aDispatcher, 5, 5, {type:"mousedown"}, aWindow);
+ EventUtils.synthesizeMouse(aDispatcher, 5, 10, {type:"mousemove"}, aWindow);
+ EventUtils.synthesizeMouse(aDispatcher, 5, 15, {type:"mousemove"}, aWindow);
+
+ aListener.removeEventListener("dragstart", trapDrag, true);
+
+ return dt;
+}
+
+/**
+ * Synthesizes a drag over event.
+ * @param {} aWindow
+ * @param {XULElement} aDispatcher
+ * the element from which the drag session should be started.
+ * @param {nsIDataTransfer} aDt
+ * the DataTransfer Object of captured by listener.
+ * @param {} aArgs
+ * arguments passed to the mouse event.
+ */
+function synthesize_drag_over(aWindow, aDispatcher, aDt, aArgs)
+{
+ _synthesizeDragEvent("dragover", aWindow, aDispatcher, aDt, aArgs);
+}
+
+/**
+ * Synthesizes a drag end event.
+ * @param {} aWindow
+ * @param {XULElement} aDispatcher
+ * the element from which the drag session should be started.
+ * @param {nsIDataTransfer} aDt
+ * the DataTransfer Object of captured by listener.
+ * @param {} aArgs
+ * arguments passed to the mouse event.
+ */
+function synthesize_drag_end(aWindow, aDispatcher, aListener, aDt, aArgs)
+{
+ _synthesizeDragEvent("dragend", aWindow, aListener, aDt, aArgs);
+
+ //Ensure drag has ended.
+ EventUtils.synthesizeMouse(aDispatcher, 5, 5, {type:"mousemove"}, aWindow);
+ EventUtils.synthesizeMouse(aDispatcher, 5, 10, {type:"mousemove"}, aWindow);
+ EventUtils.synthesizeMouse(aDispatcher, 5, 5, {type:"mouseup"}, aWindow);
+}
+
+/**
+ * Synthesizes a drop oevent.
+ * @param {} aWindow
+ * @param {XULElement} aDispatcher
+ * the element from which the drag session should be started.
+ * @param {nsIDataTransfer} aDt
+ * the DataTransfer Object of captured by listener.
+ * @param {} aArgs
+ * arguments passed to the mouse event.
+ */
+function synthesize_drop(aWindow, aDispatcher, aDt, aArgs)
+{
+ _synthesizeDragEvent("drop", aWindow, aDispatcher, aDt, aArgs);
+
+ // Ensure drag has ended.
+ EventUtils.synthesizeMouse(aDispatcher, 5, 5, {type:"mousemove"}, aWindow);
+ EventUtils.synthesizeMouse(aDispatcher, 5, 10, {type:"mousemove"}, aWindow);
+ EventUtils.synthesizeMouse(aDispatcher, 5, 5, {type:"mouseup"}, aWindow);
+}
+
+/**
+ * Private function: Synthesizes a specified drag event.
+ * @param {} aType
+ * the type of the drag event to be synthesiyzed.
+ * @param {} aWindow
+ * @param {XULElement} aDispatcher
+ * the element from which the drag session should be started.
+ * @param {nsIDataTransfer} aDt
+ * the DataTransfer Object of captured by listener.
+ * @param {} aArgs
+ * arguments passed to the mouse event.
+ */
+function _synthesizeDragEvent(aType, aWindow, aDispatcher, aDt, aArgs)
+{
+ let screenX;
+ if (aArgs && ("screenX" in aArgs))
+ screenX = aArgs.screenX;
+ else
+ screenX = aDispatcher.boxObject.ScreenX;;
+
+ let screenY;
+ if (aArgs && ("screenY" in aArgs))
+ screenY = aArgs.screenY;
+ else
+ screenY = aDispatcher.boxObject.ScreenY;
+
+ let event = aWindow.document.createEvent("DragEvents");
+ event.initDragEvent(aType, true, true, aWindow, 0,
+ screenX, screenY, 0, 0, false, false, false, false, 0, null, aDt);
+ aDispatcher.dispatchEvent(event);
+}
diff --git a/test/download.sh b/test/download.sh
new file mode 100644
index 0000000..23dbdaf
--- /dev/null
+++ b/test/download.sh
@@ -0,0 +1,20 @@
+#! /bin/bash
+
+export FTP_DIR=https://ftp.mozilla.org/pub/mozilla.org/thunderbird/nightly/5.0-candidates/build1/unsigned/win32/en-US/
+export APP=thunderbird-5.0.zip
+export TESTS=thunderbird-5.0.tests.zip
+
+wget -P ftp -N $FTP_DIR/$APP
+wget -P ftp -N $FTP_DIR/$TESTS
+
+export TESTDIR=test-5.0
+mkdir -p $TESTDIR
+
+unzip -o ftp/$APP -d $TESTDIR
+unzip -o ftp/$TESTS -d $TESTDIR -x "*mochitest*" "*xpcshell*"
+
+junction $TESTDIR/mozmill/compactheader compactheader
+# copy drag'n'drop helpers to shared-modules until they are added to thunderbird source
+cp $TESTDIR/mozmill/compactheader/test-mouse-event-helpers.js $TESTDIR/mozmill/shared-modules
+
+# python runtest.py --binary=../thunderbird/thunderbird.exe -a ../../../AMO/CompactHeader-1.4.2beta3.xpi -l log -t compactheader/test-compactheader-toolbar.js
\ No newline at end of file
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/compactheader.git
More information about the Pkg-mozext-commits
mailing list