summaryrefslogtreecommitdiffstats
path: root/comm/mail/test/browser/shared-modules/MockObjectHelpers.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mail/test/browser/shared-modules/MockObjectHelpers.jsm')
-rw-r--r--comm/mail/test/browser/shared-modules/MockObjectHelpers.jsm161
1 files changed, 161 insertions, 0 deletions
diff --git a/comm/mail/test/browser/shared-modules/MockObjectHelpers.jsm b/comm/mail/test/browser/shared-modules/MockObjectHelpers.jsm
new file mode 100644
index 0000000000..3b4ed91e53
--- /dev/null
+++ b/comm/mail/test/browser/shared-modules/MockObjectHelpers.jsm
@@ -0,0 +1,161 @@
+/* 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/. */
+
+"use strict";
+
+const EXPORTED_SYMBOLS = ["MockObjectReplacer", "MockObjectRegisterer"];
+
+var Cm = Components.manager;
+
+function MockObjectRegisterer(aContractID, aCID, aComponent) {
+ this._contractID = aContractID;
+ this._cid = Components.ID("{" + aCID + "}");
+ this._component = aComponent;
+}
+
+MockObjectRegisterer.prototype = {
+ register() {
+ let providedConstructor = this._component;
+ this._mockFactory = {
+ createInstance(aIid) {
+ return new providedConstructor().QueryInterface(aIid);
+ },
+ };
+
+ let componentRegistrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
+
+ componentRegistrar.registerFactory(
+ this._cid,
+ "",
+ this._contractID,
+ this._mockFactory
+ );
+ },
+
+ unregister() {
+ let componentRegistrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
+
+ componentRegistrar.unregisterFactory(this._cid, this._mockFactory);
+ },
+};
+
+/**
+ * Allows registering a mock XPCOM component, that temporarily replaces the
+ * original one when an object implementing a given ContractID is requested
+ * using createInstance.
+ *
+ * @param aContractID
+ * The ContractID of the component to replace, for example
+ * "@mozilla.org/filepicker;1".
+ *
+ * @param aReplacementCtor
+ * The constructor function for the JavaScript object that will be
+ * created every time createInstance is called. This object must
+ * implement QueryInterface and provide the XPCOM interfaces required by
+ * the specified ContractID (for example
+ * Ci.nsIFilePicker).
+ */
+
+function MockObjectReplacer(aContractID, aReplacementCtor) {
+ this._contractID = aContractID;
+ this._replacementCtor = aReplacementCtor;
+ this._cid = null;
+}
+
+MockObjectReplacer.prototype = {
+ /**
+ * Replaces the current factory with one that returns a new mock object.
+ *
+ * After register() has been called, it is mandatory to call unregister() to
+ * restore the original component. Usually, you should use a try-catch block
+ * to ensure that unregister() is called.
+ */
+ register() {
+ if (this._cid) {
+ throw Error("Invalid object state when calling register()");
+ }
+
+ // Define a factory that creates a new object using the given constructor.
+ var providedConstructor = this._replacementCtor;
+ this._mockFactory = {
+ createInstance(aIid) {
+ return new providedConstructor().QueryInterface(aIid);
+ },
+ };
+
+ var retVal = swapFactoryRegistration(
+ this._cid,
+ this._originalCID,
+ this._contractID,
+ this._mockFactory
+ );
+ if ("error" in retVal) {
+ throw new Error("ERROR: " + retVal.error);
+ } else {
+ this._cid = retVal.cid;
+ this._originalCID = retVal.originalCID;
+ }
+ },
+
+ /**
+ * Restores the original factory.
+ */
+ unregister() {
+ if (!this._cid) {
+ throw Error("Invalid object state when calling unregister()");
+ }
+
+ // Free references to the mock factory.
+ swapFactoryRegistration(
+ this._cid,
+ this._originalCID,
+ this._contractID,
+ this._mockFactory
+ );
+
+ // Allow registering a mock factory again later.
+ this._cid = null;
+ this._originalCID = null;
+ this._mockFactory = null;
+ },
+
+ // --- Private methods and properties ---
+
+ /**
+ * The CID under which the mock contractID was registered.
+ */
+ _cid: null,
+
+ /**
+ * The nsIFactory that was automatically generated by this object.
+ */
+ _mockFactory: null,
+};
+
+/**
+ * Swiped from mozilla/testing/mochitest/tests/SimpleTest/specialpowersAPI.js
+ */
+function swapFactoryRegistration(CID, originalCID, contractID, newFactory) {
+ let componentRegistrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
+
+ if (originalCID == null) {
+ if (contractID != null) {
+ originalCID = componentRegistrar.contractIDToCID(contractID);
+ void Cm.getClassObject(Cc[contractID], Ci.nsIFactory);
+ } else {
+ return {
+ error: "trying to register a new contract ID: Missing contractID",
+ };
+ }
+ CID = Services.uuid.generateUUID();
+
+ componentRegistrar.registerFactory(CID, "", contractID, newFactory);
+ } else {
+ componentRegistrar.unregisterFactory(CID, newFactory);
+ // Restore the original factory.
+ componentRegistrar.registerFactory(originalCID, "", contractID, null);
+ }
+
+ return { cid: CID, originalCID };
+}