How to write Greasemonkey scripts for Chrome so that you can unit-test it?

Go To StackoverFlow.com

4

I am writing a Greasemonkey user script that should use jQuery and work on Google Chrome and Firefox.

I have seen several examples of how to do this, including very good answers here on SO. And all of them boil down to calling an "injection script" function passing another callback function as parameter.

The code inside that callback function is where the "magic" happens, including access to the jQuery ($) object.

This solution works fine. But, one of the consequences of using it is that functions defined outside the callback function cannot be invoked from within it:

function doSomethingImportantThatIWantToUnitTest(){ ... }

function with_jquery(callback) {
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.textContent = "(" + callback.toString() + ")(jQuery)";
    document.body.appendChild(script);
};

with_jquery(function ($) {
    doSomethingImportantThatIWantToUnitTest(); // <---- meh. Not defined!
});


So, I can only use functions defined inside the callback function. But these functions, in turn, cannot be called from outside. In particular, they cannot be called from a unit test, for example, which is very annoying to me.

Is there a way to write Greasemonkey scripts for Chrome and yet unit-test it?

2012-04-04 17:58
by Otavio Macedo
There's a strict separation between a Content script and the page's scope. What stops you from also injecting the unit test - Rob W 2012-04-06 09:55
Your question is rather confusing since you talk about unit testing and user scripts but then when you get into the details of your problem you are talking about not being able to access functions from a particular scope. The issues of functions and scope is simply a javascript problem and not specific to userscripts or unit-testing... perhaps you should change to title and the question you are asking to be more reflective of your specific issue - Muhd 2012-04-07 01:18


1

You should be able to pass anything you want into the callback function, including function variables.

var f = function doSomethingImportantThatIWantToUnitTest(){ ... }

function with_jquery(callback) {
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.textContent = "(" + callback.toString() + ")(jQuery,f)";
    document.body.appendChild(script);
};

with_jquery(function ($, f) {
    f(); // <---- DEFINED!
});

If you have more than a few functions you want to do, and don't want to update the code in several different places, you can just pass in an object or array that has all the functions as object properties or elements in an array.

Although if it were me, I would just define the functions within the scope you are using them.

2012-04-07 00:48
by Muhd
@Rob W I tested the code and it works - Muhd 2012-04-09 18:33
Define "working". doSomethingImport... aka f is not defined in the scope of the page (that's assumed at )(jQuery,f)). Mind you: In a Content Script (Chrome), methods defined within a Content Script are not available to injected scripts - Rob W 2012-04-09 20:25
Ads