Closed nimble-software closed 11 years ago
Hi Brian,
The quickest way to do this would be:
require(['/path/to/jquery.mobile.js'], function() {
require(['/path/to/testr.js'], function() {
require(/* all your other modules */);
});
});
In other words, don't load testr.js (which intercepts the call to define
) until you've defined the modules that you don't wanted intercepted.
I'm also happy to add this as a new config option, let me know if that would be preferable.
Cheers, Matt.
Hi Matt,
Thanks for the quick reply!
I have looked into your suggestion and have found that this in itself causes problems. Let me explain.
I have the following code in my test html file.
require(['jquery'], function() {
require(['libraries/testr'], function () {
require(['view'], function (view) {
What happens is that the normal require define call is invoked to load the jquery module. I then load testr as you suggested and then load my view.
What happens is that when trojan is called for my view module, the jquery dependency that is passed in, is the jquery module instance loaded by the inital require call, not a string representing the module id, which it would have been if it's define called had been intercepted.
So at the end of the trojan call my dependency array for my view contains an object, not a string.
In my test if I then ask testr to load my view module, the following code is executed for each dependency of my view:
// load up dependencies
each(deps, function(dep) {
// determine what to pass to the factory
if (dep == 'exports') {
dep = exports;
} else if (dep === 'require') {
dep = function(path) {
return getModule(normalize(path, contextReq));
};
} else {
dep = getModule(dep); // Dep here refers to the jquery instance, not a string as expected.
}
// add dependency to array
depModules.push(dep);
});
On the line I have commented a call to getModule is invoked with the actual jquery instance. The getModule call will result in the following code being executed :
if (!moduleDef) {
// module may be stored in requirejs, e.g. plugin-loaded dependencies
try {
return require(moduleName);
} catch(e) {
throw new Error('module has not been loaded: ' + moduleName);
}
}
As there is no module definition for the jquery module (as it was loaded by the actual require define function) the require call on the object results in the incorrect dependency being returned (weirdly it appears to be the require instance itself)
I have managed to get around the problem by changing loop over the dependencies to be something like :
if (dep == 'exports') {
dep = exports;
} else if (dep === 'require') {
dep = function(path) {
return getModule(normalize(path, contextReq));
};
} else if (typeof dep === 'string') {
dep = getModule(dep);
}
If the dep is not a string, we have already loaded the module (the check could be made more robust) so don't attempt to do so again.
I am going to carry on investigating to see if I can find a slightly more elegant solution, but maybe you have some ideas?
Thanks Brian
Hi Brian, I think I've followed what's happening here. I'll take a look tonight and hopefully get a fix out to you in the next 24 hours. Cheers, Matt.
Hi Matt,
Thanks for looking into it. I have spent some more time thinking about it, and I think that the crux of the problem is that modules like jquery mobile, backbone, or I guess any module that attaches functions to jquery, expects one instance of jquery to be present, but when using testr, each of them gets a new instance of jquery when they request it as a dependency.
So for example with jquery mobile, it requests jquery as a dependency and attaches itself to jquery as $.mobile. However if you have another module that requests jquery you can't be sure which instance your application will end up operating against.
So my suggestion is that we add a config option to testr to allow the developer to specify which modules should be treated as 'singletons' for the purpose of a test run. You can then add an init function to testr which will create the required instances in the beforeEach method and a destory method which clears the singleton cache in the teardown function.
Then when you request a module, any modules that have a dependency on one of the 'singleton' modules will receive the same instance, which closer replicates real life usage.
What do you think?
Brian
Hi Brian, that's perfect, thanks for taking the time to chase this up! I'll take a look into how jquery plugins, etc, are attaching themselves to other AMD modules, and should have a fix for you shortly. Cheers, Matt.
I've traced this down to testr.js not intercepting the call to require
- working on it now :)
@nimble-software does the new v1.2.0 solve this issue?
Hi Matt
I haven't had a chance to take a look yet. Will do so and get back to you.
Regards Brian
On 15 Nov 2012, at 10:18, Matt notifications@github.com wrote:
@nimble-software https://github.com/nimble-software does the new v1.2.0 solve this issue?
— Reply to this email directly or view it on GitHubhttps://github.com/mattfysh/testr.js/issues/8#issuecomment-10403660.
On 15 Nov 2012, at 10:18, Matt notifications@github.com wrote:
@nimble-software https://github.com/nimble-software does the new v1.2.0 solve this issue?
— Reply to this email directly or view it on GitHubhttps://github.com/mattfysh/testr.js/issues/8#issuecomment-10403660.
@nimble-software apologies for the long delay! I've finally gotten around to implementing this, use the ignore
array in the config to list modules which should not be managed by testr.js. This update is included in v1.3.1.
I've create a new repo where I'm putting together a front-end dev stack, including testr.js. You can take a look how to integrate testr.js with the ignore option over at https://github.com/mattfysh/stack
Let me know if you have any troubles. Cheers!
Hi,
I am writing a mobile web app using require.js and jquery mobile. I am using testr to stub out dependencies but I am having trouble with testr intercepting the jquery mobile module, which prevents it from attaching itself correctly to jquery.
From what I can see the solution would be to add an option to the testr config, something like passThroughModules that specifies a list of modules that should be returned to require.js as is.
Does this sound feasible?
Regards Brian