diff options
Diffstat (limited to 'comm/mailnews/test/resources/PromiseTestUtils.jsm')
-rw-r--r-- | comm/mailnews/test/resources/PromiseTestUtils.jsm | 316 |
1 files changed, 316 insertions, 0 deletions
diff --git a/comm/mailnews/test/resources/PromiseTestUtils.jsm b/comm/mailnews/test/resources/PromiseTestUtils.jsm new file mode 100644 index 0000000000..cb40b8c856 --- /dev/null +++ b/comm/mailnews/test/resources/PromiseTestUtils.jsm @@ -0,0 +1,316 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * This file provides utilities useful in using Promises and Task.jsm + * with mailnews tests. + */ + +const EXPORTED_SYMBOLS = ["PromiseTestUtils"]; + +var { MailServices } = ChromeUtils.import( + "resource:///modules/MailServices.jsm" +); + +/** + * Url listener that can wrap another listener and trigger a callback. + * + * @param [aWrapped] The nsIUrlListener to pass all notifications through to. + * This gets called prior to the callback (or async resumption). + */ + +var PromiseTestUtils = {}; + +PromiseTestUtils.PromiseUrlListener = function (aWrapped) { + this.wrapped = aWrapped; + this._promise = new Promise((resolve, reject) => { + this._resolve = resolve; + this._reject = reject; + }); +}; + +PromiseTestUtils.PromiseUrlListener.prototype = { + QueryInterface: ChromeUtils.generateQI(["nsIUrlListener"]), + + OnStartRunningUrl(aUrl) { + if (this.wrapped && this.wrapped.OnStartRunningUrl) { + this.wrapped.OnStartRunningUrl(aUrl); + } + }, + OnStopRunningUrl(aUrl, aExitCode) { + if (this.wrapped && this.wrapped.OnStopRunningUrl) { + this.wrapped.OnStopRunningUrl(aUrl, aExitCode); + } + if (aExitCode == Cr.NS_OK) { + this._resolve(); + } else { + this._reject(aExitCode); + } + }, + get promise() { + return this._promise; + }, +}; + +/** + * Copy listener that can wrap another listener and trigger a callback. + * + * @param {nsIMsgCopyServiceListener} [aWrapped] - The nsIMsgCopyServiceListener + * to pass all notifications through to. This gets called prior to the + * callback (or async resumption). + */ +PromiseTestUtils.PromiseCopyListener = function (aWrapped) { + this.wrapped = aWrapped; + this._promise = new Promise((resolve, reject) => { + this._resolve = resolve; + this._reject = reject; + }); + this._result = { messageKeys: [], messageIds: [] }; +}; + +PromiseTestUtils.PromiseCopyListener.prototype = { + QueryInterface: ChromeUtils.generateQI(["nsIMsgCopyServiceListener"]), + OnStartCopy() { + if (this.wrapped && this.wrapped.OnStartCopy) { + this.wrapped.OnStartCopy(); + } + }, + OnProgress(aProgress, aProgressMax) { + if (this.wrapped && this.wrapped.OnProgress) { + this.wrapped.OnProgress(aProgress, aProgressMax); + } + }, + SetMessageKey(aKey) { + if (this.wrapped && this.wrapped.SetMessageKey) { + this.wrapped.SetMessageKey(aKey); + } + + this._result.messageKeys.push(aKey); + }, + SetMessageId(aMessageId) { + if (this.wrapped && this.wrapped.SetMessageId) { + this.wrapped.SetMessageId(aMessageId); + } + + this._result.messageIds.push(aMessageId); + }, + OnStopCopy(aStatus) { + if (this.wrapped && this.wrapped.OnStopCopy) { + this.wrapped.OnStopCopy(aStatus); + } + + if (aStatus == Cr.NS_OK) { + this._resolve(this._result); + } else { + this._reject(aStatus); + } + }, + get promise() { + return this._promise; + }, +}; + +/** + * Stream listener that can wrap another listener and trigger a callback. + * + * @param {nsIStreamListener} [aWrapped] - The nsIStreamListener to pass all + * notifications through to. This gets called prior to the callback + * (or async resumption). + */ +PromiseTestUtils.PromiseStreamListener = function (aWrapped) { + this.wrapped = aWrapped; + this._promise = new Promise((resolve, reject) => { + this._resolve = resolve; + this._reject = reject; + }); + this._data = null; + this._stream = null; +}; + +PromiseTestUtils.PromiseStreamListener.prototype = { + QueryInterface: ChromeUtils.generateQI(["nsIStreamListener"]), + + onStartRequest(aRequest) { + if (this.wrapped && this.wrapped.onStartRequest) { + this.wrapped.onStartRequest(aRequest); + } + this._data = ""; + this._stream = null; + }, + + onStopRequest(aRequest, aStatusCode) { + if (this.wrapped && this.wrapped.onStopRequest) { + this.wrapped.onStopRequest(aRequest, aStatusCode); + } + if (aStatusCode == Cr.NS_OK) { + this._resolve(this._data); + } else { + this._reject(aStatusCode); + } + }, + + onDataAvailable(aRequest, aInputStream, aOff, aCount) { + if (this.wrapped && this.wrapped.onDataAvailable) { + this.wrapped.onDataAvailable(aRequest, aInputStream, aOff, aCount); + } + if (!this._stream) { + this._stream = Cc["@mozilla.org/scriptableinputstream;1"].createInstance( + Ci.nsIScriptableInputStream + ); + this._stream.init(aInputStream); + } + this._data += this._stream.read(aCount); + }, + + get promise() { + return this._promise; + }, +}; + +/** + * Folder listener to resolve a promise when a certain folder event occurs. + * + * @param {nsIMsgFolder} folder - nsIMsgFolder to listen to + * @param {string} event - Event name to listen for. Example event is + * "DeleteOrMoveMsgCompleted". + * @returns {Promise} Promise that resolves when the event occurs. + */ +PromiseTestUtils.promiseFolderEvent = function (folder, event) { + return new Promise((resolve, reject) => { + let folderListener = { + QueryInterface: ChromeUtils.generateQI(["nsIFolderListener"]), + onFolderEvent(aEventFolder, aEvent) { + if (folder === aEventFolder && event == aEvent) { + MailServices.mailSession.RemoveFolderListener(folderListener); + resolve(); + } + }, + }; + MailServices.mailSession.AddFolderListener( + folderListener, + Ci.nsIFolderListener.event + ); + }); +}; + +/** + * Folder listener to resolve a promise when a certain folder event occurs. + * + * @param {nsIMsgFolder} folder - nsIMsgFolder to listen to. + * @param {string} listenerMethod - string listener method to listen for. + * Example listener method is "msgsClassified". + * @returns {Promise} Promise that resolves when the event occurs. + */ +PromiseTestUtils.promiseFolderNotification = function (folder, listenerMethod) { + return new Promise((resolve, reject) => { + let mfnListener = {}; + mfnListener[listenerMethod] = function () { + let args = Array.from(arguments); + let flag = true; + for (let arg of args) { + if (folder && arg instanceof Ci.nsIMsgFolder) { + if (arg == folder) { + flag = true; + break; + } else { + return; + } + } + } + + if (flag) { + MailServices.mfn.removeListener(mfnListener); + resolve(args); + } + }; + MailServices.mfn.addListener( + mfnListener, + Ci.nsIMsgFolderNotificationService[listenerMethod] + ); + }); +}; + +/** + * Folder listener to resolve a promise when a folder with a certain + * name is added. + * + * @param {string} folderName - folder name to listen for + * @returns {Promise<nsIMsgFolder>} Promise that resolves with the new folder + * when the folder add completes. + */ +PromiseTestUtils.promiseFolderAdded = function (folderName) { + return new Promise((resolve, reject) => { + var listener = { + folderAdded: aFolder => { + if (aFolder.name == folderName) { + MailServices.mfn.removeListener(listener); + resolve(aFolder); + } + }, + }; + MailServices.mfn.addListener( + listener, + Ci.nsIMsgFolderNotificationService.folderAdded + ); + }); +}; + +/** + * Timer to resolve a promise after a delay + * + * @param {integer} aDelay - Delay in milliseconds + * @returns {Promise} Promise that resolves after the delay. + */ +PromiseTestUtils.promiseDelay = function (aDelay) { + return new Promise((resolve, reject) => { + let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + timer.initWithCallback(resolve, aDelay, Ci.nsITimer.TYPE_ONE_SHOT); + }); +}; + +/** + * Search listener to resolve a promise when a search completes + * + * @param {nsIMsgSearchSession} aSearchSession - The nsIMsgSearchSession to search + * @param {nsIMsgSearchNotify} aWrapped - The nsIMsgSearchNotify to pass all + * notifications through to. This gets called prior to the callback + * (or async resumption). + */ +PromiseTestUtils.PromiseSearchNotify = function (aSearchSession, aWrapped) { + this._searchSession = aSearchSession; + this._searchSession.registerListener(this); + this.wrapped = aWrapped; + this._promise = new Promise((resolve, reject) => { + this._resolve = resolve; + this._reject = reject; + }); +}; + +PromiseTestUtils.PromiseSearchNotify.prototype = { + QueryInterface: ChromeUtils.generateQI(["nsIMsgSearchNotify"]), + onSearchHit(aHeader, aFolder) { + if (this.wrapped && this.wrapped.onSearchHit) { + this.wrapped.onSearchHit(aHeader, aFolder); + } + }, + onSearchDone(aResult) { + this._searchSession.unregisterListener(this); + if (this.wrapped && this.wrapped.onSearchDone) { + this.wrapped.onSearchDone(aResult); + } + if (aResult == Cr.NS_OK) { + this._resolve(); + } else { + this._reject(aResult); + } + }, + onNewSearch() { + if (this.wrapped && this.wrapped.onNewSearch) { + this.wrapped.onNewSearch(); + } + }, + get promise() { + return this._promise; + }, +}; |