zotero/test/content/support.js
Dan Stillman d9c32a8e90 Fix search saving, and add some unit tests
Also:

- Return an object from `Zotero.Search.prototype.getConditions()`
  instead of an array.
- Add support function `getPromiseError(promise)` to return the error
  thrown from a chain of promises, or false if none. (We could make an
  `assert.throwsAsync()`, but this allows testing of various properties
  such as `.name`, which even the built-in `assert.throws()` can't
  test.)
- Clarify some search save errors
2015-04-17 00:25:09 -04:00

177 lines
No EOL
5.2 KiB
JavaScript

/**
* Waits for a DOM event on the specified node. Returns a promise
* resolved with the event.
*/
function waitForDOMEvent(target, event, capture) {
var deferred = Zotero.Promise.defer();
var func = function(ev) {
target.removeEventListener("event", func, capture);
deferred.resolve(ev);
}
target.addEventListener(event, func, capture);
return deferred.promise;
}
/**
* Open a window. Returns a promise for the window.
*/
function loadWindow(winurl, argument) {
var win = window.openDialog(winurl, "_blank", "chrome", argument);
return waitForDOMEvent(win, "load").then(function() {
return win;
});
}
/**
* Loads a Zotero pane in a new window. Returns the containing window.
*/
function loadZoteroPane() {
return loadWindow("chrome://browser/content/browser.xul").then(function(win) {
win.ZoteroOverlay.toggleDisplay(true);
// Hack to wait for pane load to finish. This is the same hack
// we use in ZoteroPane.js, so either it's not good enough
// there or it should be good enough here.
return Zotero.Promise.delay(52).then(function() {
return win;
});
});
}
/**
* Waits for a window with a specific URL to open. Returns a promise for the window.
*/
function waitForWindow(uri) {
var deferred = Zotero.Promise.defer();
Components.utils.import("resource://gre/modules/Services.jsm");
var loadobserver = function(ev) {
ev.originalTarget.removeEventListener("load", loadobserver, false);
if(ev.target.location == uri) {
Services.ww.unregisterNotification(winobserver);
deferred.resolve(ev.target.docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
getInterface(Components.interfaces.nsIDOMWindow));
}
};
var winobserver = {"observe":function(subject, topic, data) {
if(topic != "domwindowopened") return;
var win = subject.QueryInterface(Components.interfaces.nsIDOMWindow);
win.addEventListener("load", loadobserver, false);
}};
Services.ww.registerNotification(winobserver);
return deferred.promise;
}
/**
* Waits for a single item event. Returns a promise for the item ID(s).
*/
function waitForItemEvent(event) {
var deferred = Zotero.Promise.defer();
var notifierID = Zotero.Notifier.registerObserver({notify:function(ev, type, ids, extraData) {
if(ev == event) {
Zotero.Notifier.unregisterObserver(notifierID);
deferred.resolve(ids);
}
}}, ["item"]);
return deferred.promise;
}
/**
* Looks for windows with a specific URL.
*/
function getWindows(uri) {
Components.utils.import("resource://gre/modules/Services.jsm");
var enumerator = Services.wm.getEnumerator(null);
var wins = [];
while(enumerator.hasMoreElements()) {
var win = enumerator.getNext();
if(win.location == uri) {
wins.push(win);
}
}
return wins;
}
/**
* Resolve a promise when a specified callback returns true. interval
* specifies the interval between checks. timeout specifies when we
* should assume failure.
*/
function waitForCallback(cb, interval, timeout) {
var deferred = Zotero.Promise.defer();
if(interval === undefined) interval = 100;
if(timeout === undefined) timeout = 10000;
var start = Date.now();
var id = setInterval(function() {
var success = cb();
if(success) {
clearInterval(id);
deferred.resolve(success);
} else if(Date.now() - start > timeout*1000) {
clearInterval(id);
deferred.reject(new Error("Promise timed out"));
}
}, interval);
return deferred.promise;
}
/**
* Return a promise for the error thrown by a promise, or false if none
*/
function getPromiseError(promise) {
return promise.thenReturn(false).catch(e => e);
}
/**
* Ensures that the PDF tools are installed, or installs them if not.
* Returns a promise.
*/
function installPDFTools() {
if(Zotero.Fulltext.pdfConverterIsRegistered() && Zotero.Fulltext.pdfInfoIsRegistered()) {
return Zotero.Promise.resolve(true);
}
// Begin install procedure
return loadWindow("chrome://zotero/content/preferences/preferences.xul", {
pane: 'zotero-prefpane-search',
action: 'pdftools-install'
}).then(function(win) {
// Wait for confirmation dialog
return waitForWindow("chrome://global/content/commonDialog.xul").then(function(dlg) {
// Accept confirmation dialog
dlg.document.documentElement.acceptDialog();
// Wait for install to finish
return waitForCallback(function() {
return Zotero.Fulltext.pdfConverterIsRegistered() && Zotero.Fulltext.pdfInfoIsRegistered();
}, 500, 30000).finally(function() {
win.close();
});
});
});
}
/**
* Returns a promise for the nsIFile corresponding to the test data
* directory (i.e., test/tests/data)
*/
function getTestDataDirectory() {
Components.utils.import("resource://gre/modules/Services.jsm");
var resource = Services.io.getProtocolHandler("resource").
QueryInterface(Components.interfaces.nsIResProtocolHandler),
resURI = Services.io.newURI("resource://zotero-unit-tests/data", null, null);
return Services.io.newURI(resource.resolveURI(resURI), null, null).
QueryInterface(Components.interfaces.nsIFileURL).file;
}
/**
* Resets the Zotero DB and restarts Zotero. Returns a promise resolved
* when this finishes.
*/
function resetDB() {
var db = Zotero.getZoteroDatabase();
return Zotero.reinit(function() {
db.remove(false);
}).then(function() {
return Zotero.Schema.schemaUpdatePromise;
});
}