Intercept dojo xhr call - dojo

In relation to this question, How do I fully intercept AND requeue http requests using dojo
I am interested in something similar, would dojo/aspect better suit?
Looking at the documentation here, http://dojotoolkit.org/reference-guide/1.9/dojo/aspect.html The example given shows how to intercept dojo.xhr, but dojo.xhr is deprecated since 1.8??. and replaced by dojo/request. For the new API, dojo/request/notify is recommended by dojo documentation.
I am confused which one to use or should I use both methods? So I can cover all cases where some legacy codes are still using the old dojo.xhr API.
The other complication I can think of for using both methods, may be both methods are called for the same xhr request, thus duplicating the work.

dojo.xhr is deprecated in favor of dojo/request/xhr, the documentation for which you can find here.
You can still use dojo/aspect as in the example. I've created a fiddle that does just that. The relevant code follows.
require([
'dojo/request/xhr',
'dojo/aspect'
], function(xhr, aspect) {
aspect.before(xhr, 'post', function() {
console.log('before POST');
});
// use xhr.post here...
});
If you still want to cover legacy code that uses dojo.xhr, you can extract the function you use in aspect and pass it to both objects:
function beforeXhr() {
// ...
}
aspect.before(dojo, 'xhr', beforeXhr);
aspect.before(xhr, 'post', beforeXhr);
I haven't figured out how to use dojo/aspect on functions that are returned to the require callback, which means you'd have to repeat the aspect calls for 'GET', 'PUT', 'DELETE', etc. If anyone knows how to use aspect with a function object as in this example, I'd love to know.

Related

Need clarification on setLocalDescription and RTCSessionDescription

I am trying to test/run/learn some WebRTC code and am having problem understanding this code from Mozilla:
...
var pc = new RTCPeerConnection();
...
pc.createOffer(function(offer) {
pc.setLocalDescription(new RTCSessionDescription(offer), function() {
// send the offer
}, error);
}, error);
The problem I have in understanding this is that pc.createOffer already returns an "offer" object with two properties: type and sdp. So, why is "new RTCSessionDescription(offer)" passed as an argument to pc.setLocalDescription and not "offer" itself as returned by pc.createOffer?
I read on RTCSessionDescription interface here. What did I miss?
Note that the MDN page you reference says "Draft. This page is not complete."
The code will work as written - because an RTCSessionDescription can effectively be cloned by passing one into another's constructor - but you're right that it is redundant, so I've updated the page to remove it. The object returned from createOffer will always suffice. Thanks for catching it.
Note that you still need to call new RTCSessionDescription in situations where the offer/answer comes in over the wire, for now.
But you'll be glad to know that that's being fixed as well soon: The spec recently changed, so you wont have to call the new RTCSessionDescription constructor ever. Much simpler. Note though that browsers like Firefox hasn't updated to allow this simpler syntax yet. This is just a convenience though, and there is no behavioral difference.
Update: adapter.js has a shim for this, so you can get rid of them now if you're using adapter.js.

intern test not using configured registry requestProvider in dojo

I'm following this article to mock response in dojo.
My mocker is very similar to the one in the article except this:
registry.register(/\/testIntern/, function (url, options) {
return when({
value: "Hello World"
});
In my understanding, this should map to any request that contains "/testIntern" on the address.
My testcase is quite simple:
// similar to example
var testRest= new Rest("/testIntern", true);
testRest("").then(lang.hitch(this, function (data) {
assert.deepEqual("Hello World", data.value, "Expected 'Hello World', but got" + data.value);
}));
It really should be quite simple. But when I run this test, I got 404 Not Found. It looks like the REST call in the test doesn't try to use the mocking service. Why?
You are generally correct in your thought that registering a URL with dojo/request/registry should pass anything referencing that URL via dojo/request through your handler.
Unfortunately, dojo/store/JsonRest uses the dojo/_base/xhr module which uses dojo/request/xhr directly, not dojo/request. Any registrations created with dojo/request/registry (and any setting of defaultProvider) will unfortunately be lost on JsonRest.
You might want to have a look at dstore - its Rest store implements the same server requests as dojo/store/JsonRest but it uses dojo/request instead of being hard-coded to a specific provider. (dojo/request defaults to dojo/request/xhr in browsers anyway, but can be overridden via dojoConfig.requestProvider.) dstore contains adapters for translating between dstore's API and the dojo/store API, if you need to use it with widgets that operate with the latter.

How to stub an external API for testing

I have a project that makes some calls to Twitter's API from the node.js server that I would like to test. However, I don't want to test the Twitter API (OAuth and the actual API I'm calling), so I thought it would be best to stub it out.
I found sinon.js that supports this supposedly. I have not found an example of how to do this and was wondering if this has been done before. And if so, seeing some sample code would really help.
What are you doing to call the API?
Imagine you use a method called api.call('url', function (error, response) {...}):
you can "fake" the callback with sinon, gently or whatever you like.
Example using gently:
gently.expect(api, 'call', function (url, callback) {
assert.equal(url, 'http://api.twitter.com/...');
callback(Error('Fake error'), null);
});

Mocking out AJAX calls with Dojo XHR

I'm attempting to mock the response of a dojo xhr request, but I haven't found a good solution.
Ideally, I'd like to see a solution similar to the jQuery mockjax plugin where I can set a specific call based on a url, e.g.:
$.mockjax({
url: '/restful/fortune',
responseTime: 750,
responseText: {
status: 'success',
fortune: 'Are you a turtle?'
}
});
My initial thought was to utilize the "/dojo/io/send" channel, but I haven't been able to get a modified response to be loaded after modifying the dojo Deferred object.
The other thought is to use a pass-through method that would determine if an actual xhr request should be made, e.g.:
function xhrRequest(xhrArgs) {
if(shouldMock) {
var fakeReturnJson = dojo.toJson({
howdy: "that's odd!",
isStrange: false
});
return fakeReturnJson;
} else {
dojo.xhr(xhrArgs);
}
}
Can someone tell me the best way to go about mocking dojo xhr calls?
Thanks!
It's an old question, but I think you should do your mocking using Sinon.js
However you will need to put the following:
has: { native-xhr2: false }
into your dojoConfig for it to work in 1.8
I haven't heard of any Dojo specific libraries similar to Mockjax. But what I think you could try is use Mockjax with Dojo. This should be pretty easy to do since all you'll have to do is use JQuery during development only for testing with Mockjax and then remove it once development is complete.
I use your second suggestion. Currently, I have a transport layer (simple js class) and 2 implementations (XhrTransport and MockTransport). I then switch in which I need without changing the widget code.
Widgets call the server with:
Controller.send(aServerCall);
where aServerCall is a simple value object with the server endpoint, params and callback.
This way, you can add nice things to the controller that will apply to all server calls (such as logging, analytics, generic error handling...) and also mock out the entire server when doing unit tests.
For the MockTransport, I simply return canned json data from static .js files in the format that the widget expects.

dojo.xhrGet or dojo.xhrPost

I'm very new at this, in fact this is my first Dojo attempt. I'm trying to get data from a website with:
<script
text="text/javascript"
src="http://o.aolcdn.com/dojo/1.3/dojo/dojo.xd.js"
djConfig="parseOnLoad:true,isDebug:true"
></script>
<script type="text/javascript">
//How are we supposed to know what else to include in the dojo thing? like query?
dojo.addOnLoad(function(){
console.log("hi");
dojo.xhrPost({
url: "http://www.scrapbookingsuppliesrus.com/catalog/layout", //who knows how to set relative urls?
handleAs: "json", //get json data from server
load: function(response, ioArgs){
console.log("got");
console.log(response); //helps with the debugging
return response; //that way goods should be a very large array of the data we want
},
error: function(response, ioArgs){
console.log("nope didn't make it", response+' '+ioArgs); //helps with the debugging
return response; //who knows what this does
} //last item, thus no extra comma
});
});
</script>
But nothing happens. While I'm at it, what exactly is the response and ioArgs variables. They're supposed to magically be the response to the request that I guess is specially defined already. But, who knows. Further, I figured after every attempt it would trigger something in load or error, but alas.
There used to be an error that I was going to a prohibited uri, but then firebug would reference a very large dojo script where it was impossible to tell why it was broken. What environment are the rest of you developing on?
Well, there are a couple of issues.
Lets start with the very easy ones first.
When you are developing you want to use the "uncompressed" version of Dojo, which can be found by appending .uncompressed.js to the path of the Dojo library being used:
http://o.aolcdn.com/dojo/1.3/dojo/dojo.xd.js.uncompressed.js
This will make it much easier to see what breaks, if it is in core-Dojo that is.
Next, the djConfig parameter. I'm quite certain that Dojo can handle a string, but traditionally it has been defined with an object, so, once you've included your Dojo library:
<script src="path to dojo"></script>
Start a new script block and define the djConfig object in there:
<script>
djConfig = {
parseOnLoad: true,
isDebug: true
};
</script>
Next simplest, I use IntelliJ JIDEA to develop, it has build-in code-sense for Dojo, makes life much easier. Otherwise, the standard package, Firefox + Firebug.
The complex stuff:
It seems that you are requesting data using the XHR method, hopefully you are aware that this means that your script and the data being accessed must reside on the same domain, if they don't you'll have security errors. How can this be solved? you use the technique called cross-domain scripting, which dojo also supports via the dojo.io.script.get functionality.
The more complex stuff:
Dojo works with something called "Deferred" objects. That means that the request doesn't actually go out as soon as the object is created, rather it goes out when you ask it to go out, that's the concept of "Deferred", you defer the execution of a block of code to a later time. The way this problem would then be solvedin your case is like this:
var deferred = dojo.xhrPost({
url: "http://www.scrapbookingsuppliesrus.com/catalog/layout", //who knows how to set relative urls?
handleAs: "json" //get json data from server
});
if(deferred) {
deferred.addCallback(function(response){
console.log("got");
console.log(response); //helps with the debugging
return response; //that way goods should be a very large array of the data we want
});
deferred.addErrback(function(response){
console.log("nope didn't make it", response+' '+ioArgs); //helps with the debugging
return response; //who knows what this does
});
}
And this should work out now.
As a personal note, i would not recommend using XHR but rather the dojo.io.script.get methodology, which over the long term is much more portable.
There where several very basic errors in your code.
<script ... djConfig="parseOnLoad:true,isDebug:true"/></script>
Here you use the short form of the script tag /> (which is forbidden) and at the same include the closing </script> too.
console.log("hi")
There is a semi-colon missing at the end of the statement
You try to load data from http://www.scrapbookingsuppliesrus.com/catalog/layout is your script also running on that domain? Else the security restrictions on Crossdomain-Ajax (google it) will prevent you from loading the data.
This question was also asked on the dojo-interest list and there are a few replies to the question on that list.
If your page is being served from www.scrapbookingsuppliesrus.com, then the code you've posted looks correct. The way you declare djConfig will work, and specifying load and error in the argument to xhrGet is correct. You're going to have dig in and debug.
Take a look in Firebug's Console window. You should see the GET request, complete with request and response HTTP headers, and the response text. If you don't see it, then I suspect something else has gone wrong before your onLoad function from being called - I'd throw a console.log at the top of that too. If your onLoad function isn't getting called, you may want to click the little down arrow in the Script tab and set "Break on all errors"
As to what the response and ioArgs are.
Response is, well, the response. If the request was successful, it will be the JSON object (or XML DOM object, or HTML DOM object, or text, depending on handleAs). If the request failed, it will contain an object with details about the error.
ioArgs is an object that includes a slew of lower-level details about the xhr request. As an asice, I've found that if you attach a callback to the deferred returned by xhrGet:
var dfd = dojo.xhrGet(args);
dfd.addCallbacks(function(response) {...}, function(error){...});
then the callback is not passed the ioArgs argument, just the response (or error).
dojocampus.org is the official dojo documentation site, and includes a lot of detail and examples.
Dojo: The Definitive Guide from O'Reilly is an excellent book. If you're going to be doing a lot of dojo dev., it's a great resource.
First, let's start with the basics, then you can add all the functionality.
You only need this to implement Ajax (take advantage of Dojo):
function sendData(dataToPost) {
dojo.xhrPost({
url: "http://myUrl.html",
postData: "data="+dataToPost,
handleAs: "text",
load: function(text){
getData(text);
},
error: function(error){
alert(error);
}
});
}
Now you can use the data in your "getData" function
function getData(text){
myVariable = text;
}
You can find many tutorials to see how it's implemented. This is the most complete example that I found, here you can see how it's implemented and all the code is available:
http://www.ibm.com/developerworks/java/library/j-hangman-app/index.html