2023-05-20 08:30:52 +00:00
|
|
|
const { MultimediaViewer } = require( 'mmv' );
|
|
|
|
|
2018-11-12 16:33:24 +00:00
|
|
|
( function () {
|
2023-10-24 09:53:23 +00:00
|
|
|
const MTH = {};
|
2014-01-30 07:22:26 +00:00
|
|
|
|
2014-10-03 09:15:28 +00:00
|
|
|
/**
|
|
|
|
* Returns the exception thrown by callback, or undefined if no exception was thrown.
|
2016-07-18 13:49:27 +00:00
|
|
|
*
|
2014-10-03 09:15:28 +00:00
|
|
|
* @param {Function} callback
|
2016-12-14 13:09:10 +00:00
|
|
|
* @return {Error}
|
2014-10-03 09:15:28 +00:00
|
|
|
*/
|
2014-04-14 18:32:30 +00:00
|
|
|
MTH.getException = function ( callback ) {
|
2023-10-24 09:53:23 +00:00
|
|
|
let ex;
|
2014-04-14 18:32:30 +00:00
|
|
|
try {
|
|
|
|
callback();
|
|
|
|
} catch ( e ) {
|
|
|
|
ex = e;
|
|
|
|
}
|
|
|
|
return ex;
|
|
|
|
};
|
|
|
|
|
2017-06-02 09:29:41 +00:00
|
|
|
/**
|
|
|
|
* Creates an mw.storage-like object.
|
|
|
|
*
|
|
|
|
* @param {Object} storage localStorage stub with getItem, setItem, removeItem methods
|
2017-07-10 09:42:42 +00:00
|
|
|
* @return {mw.SafeStorage} Local storage-like object
|
2017-06-02 09:29:41 +00:00
|
|
|
*/
|
|
|
|
MTH.createLocalStorage = function ( storage ) {
|
|
|
|
return new ( Object.getPrototypeOf( mw.storage ) ).constructor( storage );
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns an mw.storage that mimicks lack of localStorage support.
|
|
|
|
*
|
2017-07-10 09:42:42 +00:00
|
|
|
* @return {mw.SafeStorage} Local storage-like object
|
2017-06-02 09:29:41 +00:00
|
|
|
*/
|
|
|
|
MTH.getUnsupportedLocalStorage = function () {
|
2023-05-20 08:30:52 +00:00
|
|
|
return MTH.createLocalStorage( undefined );
|
2017-06-02 09:29:41 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns an mw.storage that mimicks localStorage being disabled in browser.
|
|
|
|
*
|
2017-07-10 09:42:42 +00:00
|
|
|
* @return {mw.SafeStorage} Local storage-like object
|
2017-06-02 09:29:41 +00:00
|
|
|
*/
|
|
|
|
MTH.getDisabledLocalStorage = function () {
|
2023-10-24 09:53:23 +00:00
|
|
|
const e = function () {
|
2017-06-02 09:29:41 +00:00
|
|
|
throw new Error( 'Error' );
|
|
|
|
};
|
|
|
|
|
2023-05-20 08:30:52 +00:00
|
|
|
return MTH.createLocalStorage( {
|
2017-06-02 09:29:41 +00:00
|
|
|
getItem: e,
|
|
|
|
setItem: e,
|
|
|
|
removeItem: e
|
|
|
|
} );
|
|
|
|
};
|
|
|
|
|
2014-10-03 09:15:28 +00:00
|
|
|
/**
|
|
|
|
* Returns a fake local storage which is not saved between reloads.
|
2016-07-18 13:49:27 +00:00
|
|
|
*
|
2017-07-10 09:42:42 +00:00
|
|
|
* @return {mw.SafeStorage} Local storage-like object
|
2014-10-03 09:15:28 +00:00
|
|
|
*/
|
2024-02-07 17:16:24 +00:00
|
|
|
MTH.getFakeLocalStorage = function () {
|
|
|
|
const bag = new Map();
|
2023-05-20 08:30:52 +00:00
|
|
|
return MTH.createLocalStorage( {
|
2024-02-07 17:16:24 +00:00
|
|
|
getItem: ( key ) => bag.get( key ) || null,
|
|
|
|
setItem: ( key, value ) => bag.set( key, value ),
|
|
|
|
removeItem: ( key ) => bag.delete( key )
|
2017-06-02 09:29:41 +00:00
|
|
|
} );
|
2014-10-03 09:15:28 +00:00
|
|
|
};
|
|
|
|
|
2016-04-03 09:18:26 +00:00
|
|
|
/**
|
|
|
|
* Returns a viewer object with all the appropriate placeholder functions.
|
2016-07-18 13:49:27 +00:00
|
|
|
*
|
2023-05-20 08:30:52 +00:00
|
|
|
* @return {MultimediaViewer}
|
2016-04-03 09:18:26 +00:00
|
|
|
*/
|
|
|
|
MTH.getMultimediaViewer = function () {
|
2023-05-20 08:30:52 +00:00
|
|
|
return new MultimediaViewer( {
|
2019-02-05 23:59:52 +00:00
|
|
|
imageQueryParameter: function () {},
|
|
|
|
language: function () {},
|
|
|
|
recordVirtualViewBeaconURI: function () {},
|
2016-04-03 09:18:26 +00:00
|
|
|
extensions: function () {
|
2016-07-18 13:49:27 +00:00
|
|
|
return { jpg: 'default' };
|
2016-04-03 09:18:26 +00:00
|
|
|
}
|
|
|
|
} );
|
|
|
|
};
|
|
|
|
|
2017-05-05 15:53:28 +00:00
|
|
|
MTH.asyncPromises = [];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Given a method/function that returns a promise, this'll return a function
|
|
|
|
* that just wraps the original & returns the original result, but also
|
|
|
|
* executes an assert.async() right before it's called, and resolves that
|
|
|
|
* async after that promise has completed.
|
|
|
|
*
|
|
|
|
* Example usage: given a method `bootstrap.openImage` that returns a
|
|
|
|
* promise, just call it like this to wrap this functionality around it:
|
|
|
|
* `bootstrap.openImage = asyncMethod( bootstrap.openImage, bootstrap );`
|
|
|
|
*
|
|
|
|
* Now, every time some part of the code calls this function, it'll just
|
|
|
|
* execute as it normally would, but your tests won't finish until these
|
|
|
|
* functions (and any .then tacked on to them) have completed.
|
|
|
|
*
|
|
|
|
* This method will make sure your tests don't end prematurely (before the
|
|
|
|
* promises have been resolved), but that's it. If you need to run
|
|
|
|
* additional code after all promises have resolved, you can call the
|
|
|
|
* complementary `waitForAsync`, which will return a promise that doesn't
|
|
|
|
* resolve until all of these promises have.
|
|
|
|
*
|
|
|
|
* @param {Object} object
|
|
|
|
* @param {string} method
|
|
|
|
* @param {QUnit.assert} [assert]
|
|
|
|
* @return {Function}
|
|
|
|
*/
|
|
|
|
MTH.asyncMethod = function ( object, method, assert ) {
|
2023-10-24 09:53:23 +00:00
|
|
|
const helpers = this;
|
2017-05-05 15:53:28 +00:00
|
|
|
return function () {
|
|
|
|
// apply arguments to original promise
|
2023-10-24 09:53:23 +00:00
|
|
|
const promise = object[ method ].apply( object, arguments );
|
2017-05-05 15:53:28 +00:00
|
|
|
|
2022-05-13 21:10:05 +00:00
|
|
|
helpers.asyncPromises.push( promise );
|
2017-05-05 15:53:28 +00:00
|
|
|
|
|
|
|
if ( assert ) {
|
2023-10-24 09:53:23 +00:00
|
|
|
const done = assert.async();
|
2017-05-05 15:53:28 +00:00
|
|
|
// use setTimeout to ensure `done` is not the first callback handler
|
|
|
|
// to execute (possibly ending the test's wait right before
|
|
|
|
// the result of the promise is executed)
|
|
|
|
setTimeout( promise.then.bind( null, done, done ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
return promise;
|
2022-05-13 21:10:05 +00:00
|
|
|
};
|
2017-05-05 15:53:28 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a promise that will not resolve until all of the promises that
|
|
|
|
* were created in functions upon which `asyncMethod` was called have
|
|
|
|
* resolved.
|
|
|
|
*
|
2020-06-26 10:45:20 +00:00
|
|
|
* @return {jQuery.Promise}
|
2017-05-05 15:53:28 +00:00
|
|
|
*/
|
|
|
|
MTH.waitForAsync = function () {
|
2023-10-24 09:53:23 +00:00
|
|
|
const deferred = $.Deferred();
|
2017-05-05 15:53:28 +00:00
|
|
|
|
|
|
|
// it's possible that, before this function call, some code was executed
|
|
|
|
// that triggers async code that will eventually end up `asyncPromises`
|
|
|
|
// in order to give that code a chance to run, we'll add another promise
|
|
|
|
// to the array, that will only resolve at the end of the current call
|
|
|
|
// stack (using setTimeout)
|
2023-05-20 08:30:52 +00:00
|
|
|
MTH.asyncPromises.push( deferred.promise() );
|
2017-05-05 15:53:28 +00:00
|
|
|
setTimeout( deferred.resolve );
|
|
|
|
|
2023-05-20 08:30:52 +00:00
|
|
|
return QUnit.whenPromisesComplete.apply( null, MTH.asyncPromises ).then(
|
2017-05-05 15:53:28 +00:00
|
|
|
function () {
|
2023-05-20 08:30:52 +00:00
|
|
|
MTH.asyncPromises = [];
|
|
|
|
}
|
2017-05-05 15:53:28 +00:00
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2023-05-20 08:30:52 +00:00
|
|
|
module.exports = MTH;
|
2018-11-12 16:33:24 +00:00
|
|
|
}() );
|