summaryrefslogtreecommitdiffstats
path: root/testing/mochitest/tests/SimpleTest/MockObjects.js
diff options
context:
space:
mode:
Diffstat (limited to 'testing/mochitest/tests/SimpleTest/MockObjects.js')
-rw-r--r--testing/mochitest/tests/SimpleTest/MockObjects.js90
1 files changed, 90 insertions, 0 deletions
diff --git a/testing/mochitest/tests/SimpleTest/MockObjects.js b/testing/mochitest/tests/SimpleTest/MockObjects.js
new file mode 100644
index 000000000..d00f5127b
--- /dev/null
+++ b/testing/mochitest/tests/SimpleTest/MockObjects.js
@@ -0,0 +1,90 @@
+/* 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/. */
+
+/**
+ * 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
+ * Components.interfaces.nsIFilePicker).
+ */
+
+function MockObjectRegisterer(aContractID, aReplacementCtor) {
+ this._contractID = aContractID;
+ this._replacementCtor = aReplacementCtor;
+}
+
+MockObjectRegisterer.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: function MOR_register() {
+ if (this._originalFactory)
+ throw new Exception("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: function MF_createInstance(aOuter, aIid) {
+ if (aOuter != null)
+ throw SpecialPowers.Cr.NS_ERROR_NO_AGGREGATION;
+ return new providedConstructor().QueryInterface(aIid);
+ }
+ };
+
+ var retVal = SpecialPowers.swapFactoryRegistration(this._cid, this._contractID, this._mockFactory, this._originalFactory);
+ if ('error' in retVal) {
+ throw new Exception("ERROR: " + retVal.error);
+ } else {
+ this._cid = retVal.cid;
+ this._originalFactory = retVal.originalFactory;
+ }
+ },
+
+ /**
+ * Restores the original factory.
+ */
+ unregister: function MOR_unregister() {
+ if (!this._originalFactory)
+ throw new Exception("Invalid object state when calling unregister()");
+
+ // Free references to the mock factory.
+ SpecialPowers.swapFactoryRegistration(this._cid, this._contractID, this._mockFactory, this._originalFactory);
+
+ // Allow registering a mock factory again later.
+ this._cid = null;
+ this._originalFactory = null;
+ this._mockFactory = null;
+ },
+
+ // --- Private methods and properties ---
+
+ /**
+ * The factory of the component being replaced.
+ */
+ _originalFactory: null,
+
+ /**
+ * The CID under which the mock contractID was registered.
+ */
+ _cid: null,
+
+ /**
+ * The nsIFactory that was automatically generated by this object.
+ */
+ _mockFactory: null
+}