]> git.donarmstrong.com Git - dactyl.git/blob - common/tests/functional/shared-modules/toolbars.js
Initial import of 1.0~b6
[dactyl.git] / common / tests / functional / shared-modules / toolbars.js
1 /* ***** BEGIN LICENSE BLOCK *****
2  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3  *
4  * The contents of this file are subject to the Mozilla Public License Version
5  * 1.1 (the "License"); you may not use this file except in compliance with
6  * the License. You may obtain a copy of the License at
7  * http://www.mozilla.org/MPL/
8  *
9  * Software distributed under the License is distributed on an "AS IS" basis,
10  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11  * for the specific language governing rights and limitations under the
12  * License.
13  *
14  * The Original Code is MozMill Test code.
15  *
16  * The Initial Developer of the Original Code is Mozilla Foundation.
17  * Portions created by the Initial Developer are Copyright (C) 2009
18  * the Initial Developer. All Rights Reserved.
19  *
20  * Contributor(s):
21  *   Henrik Skupin <hskupin@mozilla.com>
22  *   Aaron Train <atrain@mozilla.com>
23  *
24  * Alternatively, the contents of this file may be used under the terms of
25  * either the GNU General Public License Version 2 or later (the "GPL"), or
26  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27  * in which case the provisions of the GPL or the LGPL are applicable instead
28  * of those above. If you wish to allow use of your version of this file only
29  * under the terms of either the GPL or the LGPL, and not to allow others to
30  * use your version of this file under the terms of the MPL, indicate your
31  * decision by deleting the provisions above and replace them with the notice
32  * and other provisions required by the GPL or the LGPL. If you do not delete
33  * the provisions above, a recipient may use your version of this file under
34  * the terms of any one of the MPL, the GPL or the LGPL.
35  *
36  * ***** END LICENSE BLOCK ***** */
37
38 /**
39  * @fileoverview
40  * The ToolbarAPI adds support for accessing and interacting with toolbar elements
41  *
42  * @version 1.0.0
43  */
44
45 // Include required modules
46 var utils = require("utils");
47
48 const TIMEOUT = 5000;
49
50 const AUTOCOMPLETE_POPUP = '/id("main-window")/id("mainPopupSet")/id("PopupAutoCompleteRichResult")';
51 const NOTIFICATION_POPUP = '/id("main-window")/id("mainPopupSet")/id("notification-popup")';
52 const URLBAR_CONTAINER = '/id("main-window")/id("tab-view-deck")/{"flex":"1"}' +
53                          '/id("navigator-toolbox")/id("nav-bar")/id("urlbar-container")';
54 const URLBAR_INPUTBOX = URLBAR_CONTAINER + '/id("urlbar")/anon({"anonid":"stack"})' + 
55                                            '/anon({"anonid":"textbox-container"})' + 
56                                            '/anon({"anonid":"textbox-input-box"})';
57 const CONTEXT_MENU = URLBAR_INPUTBOX + '/anon({"anonid":"input-box-contextmenu"})';
58
59 /**
60  * Constructor
61  * 
62  * @param {MozmillController} controller
63  *        MozMillController of the window to operate on
64  */
65 function autoCompleteResults(controller) {
66   this._controller = controller;
67   this._popup = this.getElement({type: "popup"});
68   this._results = this.getElement({type: "results"});
69 }
70
71 /**
72  * AutoComplete Result class
73  */
74 autoCompleteResults.prototype = {
75   /**
76    * Returns all autocomplete results
77    *
78    * @returns Autocomplete results
79    * @type {Array of ElemBase}
80    */
81   get allResults() {
82     var results = [];
83     for (ii = 0; ii < this.length; ii++) {
84       results.push(this.getResult(ii));
85     }
86     return results;
87   },
88
89   /**
90    * Returns the controller of the current window
91    *
92    * @returns Mozmill Controller
93    * @type MozMillController
94    */
95   get controller() {
96     return this._controller;
97   },
98
99   /**
100    * Check if the autocomplete popup is open
101    *
102    * @returns True if the panel is open
103    * @type {boolean}
104    */
105   get isOpened() {
106     return (this._popup.getNode().state == 'open');
107   },
108
109   /**
110    * Return the amount of autocomplete entries
111    *
112    * @returns Number of all entries
113    * @type {number}
114    */
115   get length() {
116     return this._results.getNode().itemCount;
117   },
118
119   /**
120    * Returns the currently selected index
121    *
122    * @returns Selected index
123    * @type {number}
124    */
125   get selectedIndex() {
126     return this._results.getNode().selectedIndex;
127   },
128
129   /**
130    * Returns the visible autocomplete results
131    *
132    * @returns Results
133    * @type {Array of ElemBase}
134    */
135   get visibleResults() {
136     var results = [];
137     for (ii = 0; ii < this.length; ii++) {
138       var result = this.getResult(ii);
139       if (!result.getNode().hasAttribute("collapsed"))
140         results.push(result);
141     }
142     return results;
143   },
144
145   /**
146    * Returns the underlined text of all results from the text or URL
147    *
148    * @param {ElemBase} result
149    *        Autocomplete result which has to be checked
150    * @param {string} type
151    *        Type of element to check (text or url)
152    *
153    * @returns An array of substrings which are underlined
154    * @type {Array of string}
155    */
156   getUnderlinedText : function autoCompleteResults_getUnderlinedText(result, type) {
157     this._controller.assertJS("subject.resultNode != null",
158                               {resultNode: result.getNode()});
159
160     // Get the description element of the given title or url
161     var description = null;
162     switch (type) {
163       case "title":
164         description = result.getNode().boxObject.firstChild.childNodes[1].childNodes[0];
165         break;
166       case "url":
167         description = result.getNode().boxObject.lastChild.childNodes[2].childNodes[0];
168         break;
169       default:
170         throw new Error(arguments.callee.name + ": Type unknown - " + type);
171     }
172
173     let values = [ ];
174     for each (node in description.childNodes) {
175       if (node.nodeName == 'span') {
176         // Only add underlined text to the results
177         values.push(node.innerHTML);
178       }
179     }
180
181     return values;
182   },
183
184   /**
185    * Gets all the needed external DTD urls as an array
186    *
187    * @returns Array of external DTD urls
188    * @type [string]
189    */
190   getDtds : function autoCompleteResults_getDtds() {
191     return null;
192   },
193
194   /**
195    * Retrieve an UI element based on the given spec
196    *
197    * @param {object} spec
198    *        Information of the UI element which should be retrieved
199    *        type: General type information
200    *        subtype: Specific element or property
201    *        value: Value of the element or property
202    * @returns Element which has been created
203    * @type {ElemBase}
204    */
205   getElement : function autoCompleteResults_getElement(spec) {
206     var elem = null;
207
208     switch (spec.type) {
209       /**
210        * subtype: subtype to match
211        * value: value to match
212        */
213       case "popup":
214         elem = new elementslib.Lookup(this._controller.window.document, AUTOCOMPLETE_POPUP);
215         break;
216       case "results":
217         elem = new elementslib.Lookup(this._controller.window.document,
218                                       AUTOCOMPLETE_POPUP + '/anon({"anonid":"richlistbox"})');
219         break;
220       case "result":
221         elem = new elementslib.Elem(this._results.getNode().getItemAtIndex(spec.value));
222         break;
223       default:
224         throw new Error(arguments.callee.name + ": Unknown element type - " + spec.type);
225     }
226
227     return elem;
228   },
229
230   /**
231    * Returns the autocomplete result element of the given index
232    *
233    * @param {number} index
234    *        Index of the result to return
235    * @returns Autocomplete result element
236    * @type {ElemBase}
237    */
238   getResult : function autoCompleteResults_getResult(index) {
239     return this.getElement({type: "result", value: index});
240   },
241   
242   /**
243    * Close the autocomplete popup
244    * 
245    * @param {boolean} force
246    *        Force the closing of the autocomplete popup
247    */
248   close : function autoCompleteResults_close(force) {
249     if (this.isOpened) {
250       if (force) {
251         this._popup.getNode().hidePopup();
252       } else {
253         this._controller.keypress(locationBar.urlbar, "VK_ESCAPE", {});
254       }
255       this._controller.waitFor(function () {
256           return !this.isOpened;
257       }, "Autocomplete list should not be open.");
258     }
259   }
260 }
261
262 /**
263  * Constructor
264  * 
265  * @param {MozmillController} controller
266  *        MozMillController of the window to operate on
267  */
268 function locationBar(controller)
269 {
270   this._controller = controller;
271   this._autoCompleteResults = new autoCompleteResults(controller);
272 }
273
274 /**
275  * Location Bar class
276  */
277 locationBar.prototype = {
278   /**
279    * Returns the autocomplete object
280    *
281    * @returns Autocomplete object
282    * @type {object}
283    */
284   get autoCompleteResults() {
285     return this._autoCompleteResults;
286   },
287
288   /**
289    * Returns the controller of the current window
290    *
291    * @returns Mozmill controller
292    * @type {MozMillController}
293    */
294   get controller() {
295     return this._controller;
296   },
297
298   /**
299    * Returns the urlbar element
300    *
301    * @returns URL bar
302    * @type {ElemBase}
303    */
304   get urlbar() {
305     return this.getElement({type: "urlbar"});
306   },
307
308   /**
309    * Returns the currently shown URL
310    *
311    * @returns Text inside the location bar
312    * @type {string}
313    */
314   get value() {
315     return this.urlbar.getNode().value;
316   },
317
318   /**
319    * Clear the location bar
320    */
321   clear : function locationBar_clear() {
322     this.focus({type: "shortcut"});
323     this._controller.keypress(this.urlbar, "VK_DELETE", {});
324     this._controller.waitForEval("subject.value == ''",
325                                  TIMEOUT, 100, this.urlbar.getNode());
326   },
327
328   /**
329    * Close the context menu of the urlbar input field
330    */
331   closeContextMenu : function locationBar_closeContextMenu() {
332     var menu = this.getElement({type: "contextMenu"});
333     this._controller.keypress(menu, "VK_ESCAPE", {});
334   },
335
336   /**
337    * Check if the location bar contains the given text
338    *
339    * @param {string} text
340    *        Text which should be checked against
341    */
342   contains : function locationBar_contains(text) {
343     return this.urlbar.getNode().value.indexOf(text) != -1;
344   },
345
346   /**
347    * Focus the location bar
348    *
349    * @param {object} event
350    *        Focus the location bar with the given event (click or shortcut)
351    */
352   focus : function locationBar_focus(event) {
353     switch (event.type) {
354       case "click":
355         this._controller.click(this.urlbar);
356         break;
357       case "shortcut":
358         var cmdKey = utils.getEntity(this.getDtds(), "openCmd.commandkey");
359         this._controller.keypress(null, cmdKey, {accelKey: true});
360         break;
361       default:
362         throw new Error(arguments.callee.name + ": Unkown event type - " + event.type);
363     }
364
365     // Wait until the location bar has been focused
366     this._controller.waitForEval("subject.getAttribute('focused') == 'true'",
367                                  TIMEOUT, 100, this.urlbar.getNode());
368   },
369
370   /**
371    * Gets all the needed external DTD urls as an array
372    *
373    * @returns Array of external DTD urls
374    * @type [string]
375    */
376   getDtds : function locationBar_getDtds() {
377     var dtds = ["chrome://branding/locale/brand.dtd",
378                 "chrome://browser/locale/browser.dtd"];
379     return dtds;
380   },
381
382   /**
383    * Retrieve an UI element based on the given spec
384    *
385    * @param {object} spec
386    *        Information of the UI element which should be retrieved
387    *        type: General type information
388    *        subtype: Specific element or property
389    *        value: Value of the element or property
390    * @returns Element which has been created
391    * @type ElemBase
392    */
393   getElement : function locationBar_getElement(spec) {
394     var elem = null;
395
396     switch(spec.type) {
397       /**
398        * subtype: subtype to match
399        * value: value to match
400        */
401       case "contextMenu":
402         elem = new elementslib.Lookup(this._controller.window.document, CONTEXT_MENU);
403         break;
404       case "contextMenu_entry":
405         elem = new elementslib.Lookup(this._controller.window.document, CONTEXT_MENU +
406                                       '/{"cmd":"cmd_' + spec.subtype + '"}');
407         break;
408       case "favicon":
409         elem = new elementslib.ID(this._controller.window.document, "page-proxy-favicon");
410         break;
411       case "feedButton":
412         elem = new elementslib.ID(this._controller.window.document, "feed-button");
413         break;
414       case "goButton":
415         elem = new elementslib.ID(this._controller.window.document, "urlbar-go-button");
416         break;
417       case "historyDropMarker":
418         elem = new elementslib.Lookup(this._controller.window.document,
419                                       URLBAR_CONTAINER + '/id("urlbar")/anon({"anonid":"historydropmarker"})');
420         break;
421       case "identityBox":
422         elem = new elementslib.ID(this._controller.window.document, "identity-box");
423         break;
424       case "notification_element":
425         elem = new elementslib.Lookup(this._controller.window.document, NOTIFICATION_POPUP +
426                                       spec.subtype);
427         break;
428       case "notification_popup":
429         elem = new elementslib.Lookup(this._controller.window.document, NOTIFICATION_POPUP);
430         break;
431       case "starButton":
432         elem = new elementslib.ID(this._controller.window.document, "star-button");
433         break;
434       case "stopButton":
435         elem = new elementslib.ID(this._controller.window.document, "urlbar-stop-button");
436         break;
437       case "urlbar":
438         elem = new elementslib.ID(this._controller.window.document, "urlbar");
439         break;
440       case "urlbar_input":
441         elem = new elementslib.Lookup(this._controller.window.document, URLBAR_INPUTBOX +
442                                       '/anon({"anonid":"input"})');
443         break;
444       default:
445         throw new Error(arguments.callee.name + ": Unknown element type - " + spec.type);
446     }
447
448     return elem;
449   },
450
451   /**
452    * Retrieves the notification popup
453    * 
454    * @return The notification popup element
455    * @type {ElemBase}
456    */
457   getNotification : function locationBar_getNotification() { 
458     return this.getElement({type: "notification_popup"});
459   },
460
461   /**
462    * Retrieves the specified element of the door hanger notification bar
463    *
464    * @param {string} aType
465    *        Type of the notification bar to look for
466    * @param {string} aLookupString
467    *        Lookup string of the notification bar's child element
468    *        [optional - default: ""]
469    *
470    * @return The created element
471    * @type {ElemBase}
472    */
473   getNotificationElement : function locationBar_getNotificationElement(aType, aLookupString)
474   {
475     var lookup = '/id("' + aType + '")';
476     lookup = aLookupString ? lookup + aLookupString : lookup;
477
478     // Get the notification and fetch the child element if wanted
479     return this.getElement({type: "notification_element", subtype: lookup});
480   },
481
482   /**
483    * Load the given URL
484    *
485    * @param {string} url
486    *        URL of web page to load
487    */
488   loadURL : function locationBar_loadURL(url) {
489     this.focus({type: "shortcut"});
490     this.type(url);
491     this._controller.keypress(this.urlbar, "VK_RETURN", {});
492   },
493
494   /**
495    * Type the given text into the location bar
496    *
497    * @param {string} text
498    *        Text to enter into the location bar
499    */
500   type : function locationBar_type(text) {
501     this._controller.type(this.urlbar, text);
502     this.contains(text);
503   }
504 }
505
506 // Export of classes
507 exports.locationBar = locationBar;
508 exports.autoCompleteResults = autoCompleteResults;
509