1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/testing/mochitest/tests/SimpleTest/MockObjects.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,90 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +/** 1.9 + * Allows registering a mock XPCOM component, that temporarily replaces the 1.10 + * original one when an object implementing a given ContractID is requested 1.11 + * using createInstance. 1.12 + * 1.13 + * @param aContractID 1.14 + * The ContractID of the component to replace, for example 1.15 + * "@mozilla.org/filepicker;1". 1.16 + * 1.17 + * @param aReplacementCtor 1.18 + * The constructor function for the JavaScript object that will be 1.19 + * created every time createInstance is called. This object must 1.20 + * implement QueryInterface and provide the XPCOM interfaces required by 1.21 + * the specified ContractID (for example 1.22 + * Components.interfaces.nsIFilePicker). 1.23 + */ 1.24 + 1.25 +function MockObjectRegisterer(aContractID, aReplacementCtor) { 1.26 + this._contractID = aContractID; 1.27 + this._replacementCtor = aReplacementCtor; 1.28 +} 1.29 + 1.30 +MockObjectRegisterer.prototype = { 1.31 + /** 1.32 + * Replaces the current factory with one that returns a new mock object. 1.33 + * 1.34 + * After register() has been called, it is mandatory to call unregister() to 1.35 + * restore the original component. Usually, you should use a try-catch block 1.36 + * to ensure that unregister() is called. 1.37 + */ 1.38 + register: function MOR_register() { 1.39 + if (this._originalFactory) 1.40 + throw new Exception("Invalid object state when calling register()"); 1.41 + 1.42 + // Define a factory that creates a new object using the given constructor. 1.43 + var providedConstructor = this._replacementCtor; 1.44 + this._mockFactory = { 1.45 + createInstance: function MF_createInstance(aOuter, aIid) { 1.46 + if (aOuter != null) 1.47 + throw SpecialPowers.Cr.NS_ERROR_NO_AGGREGATION; 1.48 + return new providedConstructor().QueryInterface(aIid); 1.49 + } 1.50 + }; 1.51 + 1.52 + var retVal = SpecialPowers.swapFactoryRegistration(this._cid, this._contractID, this._mockFactory, this._originalFactory); 1.53 + if ('error' in retVal) { 1.54 + throw new Exception("ERROR: " + retVal.error); 1.55 + } else { 1.56 + this._cid = retVal.cid; 1.57 + this._originalFactory = retVal.originalFactory; 1.58 + } 1.59 + }, 1.60 + 1.61 + /** 1.62 + * Restores the original factory. 1.63 + */ 1.64 + unregister: function MOR_unregister() { 1.65 + if (!this._originalFactory) 1.66 + throw new Exception("Invalid object state when calling unregister()"); 1.67 + 1.68 + // Free references to the mock factory. 1.69 + SpecialPowers.swapFactoryRegistration(this._cid, this._contractID, this._mockFactory, this._originalFactory); 1.70 + 1.71 + // Allow registering a mock factory again later. 1.72 + this._cid = null; 1.73 + this._originalFactory = null; 1.74 + this._mockFactory = null; 1.75 + }, 1.76 + 1.77 + // --- Private methods and properties --- 1.78 + 1.79 + /** 1.80 + * The factory of the component being replaced. 1.81 + */ 1.82 + _originalFactory: null, 1.83 + 1.84 + /** 1.85 + * The CID under which the mock contractID was registered. 1.86 + */ 1.87 + _cid: null, 1.88 + 1.89 + /** 1.90 + * The nsIFactory that was automatically generated by this object. 1.91 + */ 1.92 + _mockFactory: null 1.93 +}