Last active
February 11, 2024 22:31
-
-
Save thecodedrift/6894733 to your computer and use it in GitHub Desktop.
Shim your AMD
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
================================================================================ | |
ABOUT THIS FILE - amd shim https://gist.github.com/Jakobo/6894733 | |
================================================================================ | |
This file is a helper shim for pure AMD modules. When writing an AMD module, | |
you need to have access to a global "define" method. This creates a global | |
define(), a global require(), and a global AMD object. | |
define/require work like proper sinon stubs. Any define() calls that happen | |
before your test are automatically queued to run. You can then stub out | |
define() to respond how you need it to, including expectations. | |
AMD.run() allows you to "unpause" your loader, running through your | |
define() statements as if you are doing them for the first time; this time | |
with sinon stubs. | |
AMD.exports is an array [] containing the exports. It's sequentially | |
written to for every define() call made. | |
*/ | |
var AMD = {}; | |
var define; | |
var require; | |
(function() { | |
var exports = []; | |
var queue = []; | |
var oldDefine = define; | |
var oldRequire = require; | |
// replace the global define if it exists with a generic buffer | |
define = function() { | |
queue.push([].slice.call(arguments, 0)); | |
}; | |
define.amd = true; | |
var resolveDefineCall = function(args) { | |
var resolved = null; | |
var factory = null; | |
// swap the "factory" object if it is a function with an interceptor | |
// this saves all the "resolved" variables transparently to the end | |
// user | |
factory = args.pop(); | |
if (typeof factory == 'function') { | |
args.push(function() { | |
resolved = [].slice.call(arguments, 0); | |
}); | |
} | |
// through sinon we go! | |
define.apply(define, args); | |
// if the factory was a function, run it with our resolved things | |
// otherwise, return the object literal | |
if (typeof factory == 'function') { | |
exports.push(factory.apply(factory, resolved)); | |
} | |
else { | |
exports.push(factory); | |
} | |
}; | |
// initializes a sinon version of the AMD environment | |
AMD.init = function(stubber) { | |
if (!stubber && !sinon) { | |
throw new Error('AMD Shim requires at least some mock generator. We recommend sinon.js'); | |
} | |
if (!stubber) { | |
stubber = sinon.stub; | |
} | |
define = stubber(); | |
require = stubber(); | |
AMD.ready = true; | |
}; | |
// tun through all our define() statements now that we've stubbed them out | |
// exports end up in AMD.exports | |
AMD.run = function() { | |
if (!AMD.ready) { | |
throw new Error('You must call AMD.init() to stub define and require first'); | |
} | |
// empty the buffer, and shove each item through sinon.js | |
// a while loop ensures more define() goes through sinon | |
var args = queue.shift(); | |
while (args) { | |
resolveDefineCall(args); | |
args = queue.shift(); | |
} | |
}; | |
AMD.restore = function() { | |
AMD.ready = false; | |
define = oldDefine; | |
require = oldRequire; | |
}; | |
// all exports from define()d items | |
AMD.exports = exports; | |
}(typeof sinon != 'undefined')); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 1. Include amd.js | |
// 2. Include your AMD module | |
// 3. Create local mocks that are your dependencies | |
var myMock = { | |
foo: sinon.stub(), | |
bar: sinon.stub() | |
}; | |
var myOtherMock = { | |
baz: sinon.stub(); | |
quux: sinon.stub(); | |
}; | |
// 4. define is sinon compatible by the time you get here | |
// when it's called, call the callback (2) with our mocks. | |
// if your "exports" was just an object literal, you | |
// don't need this line. | |
AMD.init(); | |
define.callsArgWith(2, myMock, myOtherMock); | |
// 5. run all AMD modules (amd.js was holding them for you) | |
AMD.run(); | |
// 6. test your exports! | |
// yes, this is a contrived example to illustrate | |
describe('my module test', funciton() { | |
var myModule = AMD.exports[0]; // ... use normally | |
it('should exist', function() { | |
expect(myModule).to.be.ok(); | |
}); | |
}); | |
// 7. restore variables | |
AMD.restore(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Were you going to commit AMD.js to trunk? I kinda need it. :)