Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In tests: Make sure all JS is loaded with requirejs

I'm having some problems with our feature specs. I currently suspect requirejs to be the evildoer. It seems that our specs (Rails with capybara-webkit) start running before all JavaScript files are loaded. Capybara-webkit allows me to evaluate Javascript in Webkit, and I would like to use that to make sure that everything is in place before I start the test run.

Can I somehow query requirejs for the modules it loaded? Are there events I can listen to? Or can I inject a requirejs module at test runtime to set a global state that I can query from my tests (not really my preferred solution)?

I'm not a requirejs expert and haven't implemented much of our JavaScript, but I need to fix it ;)

like image 815
iGEL Avatar asked Oct 16 '13 17:10

iGEL


1 Answers

"Loaded" is a bit vague word.

If it means the request is made for the module. its specified. as soon as a the module is required anywhere, either as a dependency of a module definition or a require call with the module name, following returns true.

require.specified(moduleID);

Once the module is resolved and is loaded in memory, or in other words once the module's source is fetched and loaded and the module's definition function is finished execution. following returns true.

require.defined(moduleID);

you can also look it up in requirejs.s.contexts._.defined. It's a bit of a hackish way to inspect the data structure of a lib like this, but works in browser (firebug) in case you want to insure a module is loaded or not. I have tested following with firebug and requirejs 2.1.4.

console.log(window.requirejs.s.contexts._.defined['SOME_MODULE']);

this method also helps in inspecting the inner content (properties of object/prototype) of modules with firebug.

if requirement is to ensure that a critical module loaded before executing the code further. the require call with a success callback works.

require([moduleID], function(moduleExport){
    //The module is loaded, proceed to the next step
    //This is also an inherent load check
}, function (error) {
    //The module cant be loaded, handle the exception case
});

Following snippet shows every one of above

console.log(require.specified('TEST_MODULE'));  //false if the module isn't required yet

require(['TEST_MODULE'], function(TEST_MODULE){
   console.log(require.defined('TEST_MODULE'));  //true
   console.log(require.s.contexts._.defined['TEST_MODULE'] ? true : false);  //true
}, function (error) {
   console.log('TEST_MODULE cant be loaded');
});
console.log(require.defined('TEST_MODULE'));  //false if the module isn't ready yet
console.log(require.specified('TEST_MODULE'));  //true

** requirejs can be used instead of require in case require is used for some other purpose in global scope.

** All of the above assumes that you have a reference to require/requirejs [global] wherever you are testing.

like image 125
Mohit Avatar answered Sep 19 '22 13:09

Mohit