unit test receiving binary response with $httpBackend - javascript

I have a service that processes a binary response from a web API call:
$http.get('/endpoint', {
params: urlparams,
transformResponse: transform,
responseType: 'arraybuffer'
});
Which I'm trying to test using $httpBackend:
$httpBackend.expectGET('/endpoint').respond(200, data);
But it doesn't work, because data is converted to JSON automatically and I couldn't find a way to specify the responseType in the expectGET call.
How can I make expectGET provide an binary response to the $http.get call? I've tried converting data to an ArrayBuffer to no avail.

I've had a similar issue and used:
$httpBackend.expectGET('/endpoint').respond(200, new Blob([data]));
I however had to update PhantomJs to 2.x from 1.x for this to work.

Related

get JSON from a Promise

I am using mocha to test a promise that is written in a separate javascript file. I am trying to send data to the promise with a POST request, although I'm not sure what the url should be. Here's what I have so far, using request-promise:
var rp = require('request-promise');
var options = {
method: 'POST',
url: '/algorithm.js',
body: data,
json: true // Automatically stringifies the body to JSON
};
rp(options)
.then(function(body){
count++;
done();
});
The error states that I have an invalid url, although I'm not sure how else to POST to promise inside of a javascript file.
I am trying to send data to the promise with a POST request
You can't do that, at least not directly.
POST requests are for sending data to HTTP servers.
Promises are a JavaScript object for handling asynchronous operations.
These are different things.
algorithm.js needs to either contain code that you can call directly, in which case you should require that code and then call the function.
var algorithm = require("algorithm");
if (algorithm.something()) {
count++;
}
done();
… or it should be server side JavaScript that you need to run an HTTP server for. Once you run the HTTP server, you'll be able to use code like what you wrote in the question, but you'll need to provide an absolute URL since you need to say you are using HTTP and localhost and so on.
var options = {
method: 'POST',
url: 'http://localhost:7878/route/to/algorithm',
body: data,
json: true // Automatically stringifies the body to JSON
};

How to get data from window.fetch() response?

I'm trying to use window.fetch() to get json from the server, but can't get the data from the response.
I have this code:
let url =
'https://api.flightstats.com/flex/schedules/rest/v1/json/from/SYD/to/MEL/departing/2016/3/28?appId=f4b1b6c9&appKey=59bd8f0274f2ae88aebd2c1db7794f7f';
let request = new Request (url, {
method: 'GET',
mode: 'no-cors'
});
fetch(request)
.then(function(response){
console.log(response)
});
It seems that this request is successfull, I see status 200
and response body with json in network tab - status and response. But in console.log I dont see json object - console log image
I cant understand why I dont see json in console.log
The host site you are requesting from does not appear to support CORS. As such, you can't use fetch() to make a cross origin request and get the data back. If, you change your fetch() request to mode: 'cors', the debug console will show that the host site does not offer CORS headers to allow the browser to show you the result of the request.
When you are using mode: 'no-cors', the browser is hiding the result from you (because you don't have permission to see it) and you can see the response is tagged as opaque.
In a little poking around on the api.flightstats.com site, I did see that it supports JSONP which will allow you to work around the lack of CORS support issue and successfully complete a cross origin request.
For simplicity of showing that it can work, I used jQuery to just prove that a JSONP request can be made. Here's that code in a working snippet. Note I changed the URL from /json/ to /jsonp/ and specific dataType: "jsonp" in the jQuery request. This causes jQuery to add the callback=xxxxx query parameter and to fetch the response via that corresponding script (the JSONP method).
var url =
'https://api.flightstats.com/flex/schedules/rest/v1/jsonp/from/SYD/to/MEL/departing/2016/3/28?appId=f4b1b6c9&appKey=59bd8f0274f2ae88aebd2c1db7794f7f';
$.ajax(url, {dataType: "jsonp"}).then(function(response) {
log(response);
}, function(err) {
log("$.ajax() error:")
log(err);
})
<script src="http://files.the-friend-family.com/log.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
If you take a look at the documentation of the Fetch API; you'll notice that the API offers various methods to extract the data:
arrayBuffer()
blob()
json()
text()
formData()
Assuming the response is valid JSON (which I've noticed it doesn't seem to appear), you can use the response.json() function to retrieve the response data. This also uses a Promise mechanism, as for everything with the Fetch API.
response.json().then(function(data) {
console.log(data);
});

IE8 changing GET request to POST: Angular $http

I am making call to a REST service from my AngularJS app using $http. The issue is whenever I make a GET request from IE8, it gets converted to POST request. Calls with other http methods (POST,PUT) work fine. This happens only with IE8.
Here is my code
```
var request = {method: method, url: url, data: payload};
var promise = $http(request) .then(function (response) {
return response;
});
```
Can someone please help. I have tried sending different types off data payload : null,undefined,empty object, some object. But nothing worked.
I think I have found the solution. We need to send empty string as payload. Or, use $http.get

AngularJS: PUT binary data from ArrayBuffer to the server

Ok, so I try to read a PDF file like this:
reader.readAsArrayBuffer(file);
and then try to send it to the server using $http like this:
$http.put(url, data, {headers: {'Content-Type': 'application/pdf'}});
So, just read & send the binary to the server in raw form. According to some resources I found, passing an ArrayBuffer to XHR should work, but passing it as data to $http just results in a request body like this: {} and Content-Length=2
Reading the file readAsBinaryString() results in a corrupted file (and is apparently deprecated for that very reason)
The use case seems so trivial to me, am I missing something?
Chrome 36, Angular 1.2.20
You have to use reader.readAsArrayBuffer(file); then in the onload callback create an ArrayBufferView from the result:
new Uint8Array(reader.result)
pass that data to $http and overwrite the transformRequest property so angularjs doesn't encode your array into json:
reader.onload = function() {
$http({
method: 'PUT',
headers: {'Content-Type': 'application/pdf'},
data: new Uint8Array(reader.result),
transformRequest: []
})
};
reader.readAsArrayBuffer(file);
Is it because you are just handing the $http method the array buffer instead of writing that buffer into a byte array? If so what you are posting to the server is probably just the arraybuffer object.
Check this post on how to write ArrayBuffer to byte array:
How do I read binary data to a byte array in Javascript?
There are two problems in your request.
You need to supply a data view to $http function.
So, data should be new DataView(data) or new Uint8Array(data) etc
$http always attempt to send the data as json. You can prevent this if you override the transform function. The transform function is the agent that is responsible for transforming your binary into json.
So, you should add transformRequest: [] property to your request.
Example:
var request = $http({
method: 'PUT',
url: 'example.com',
data: new Uint8Array(data),
headers: {'Content-Type': 'application/octet-stream'},
transformRequest: [],
responseType: 'arraybuffer'
});

transform request data with resource service in angular

I'm trying to send just the array of my data to the server. I found this post discussing how to send an array, but I can't get it to work.
AngularJS: ngResource and array of object as params to URL
The problem I am having is my resource gets sent back to me as JSON like this
{
Results: []
}
So when I ask for my resources,
var collaboratorResource = api.CollaboratorList.get({Id: Id });
but then, if I try something like
collaboratorResource.$save($scope.collaborators);
When I look at firebug, it shows that my data is being sent as
{
Results: []
}
when in reality, I don't want to send the data as an object with the array as a Results property. I want to send it just as an array []. I need to do that since the api is legacy and expects that.
I've been trying to see if transformRequest works, like if I did
collaboratorResource.$save({data: $scope.collaborators, transformRequest: function (data, headers) { return data.results; }});
collaboratorResource.$save({}, $scope.collaborators);
collaboratorResource.$save($scope.collaborators);
But that doesn't seem to work either. Is this even possible? As an aside, if I use $http like this, it works:
$http({ method: "POST", data: $scope.collaborators, url: collaboratorUrl });
I'm just not sure how to use the $resource service properly since I'd prefer to wrap everything in $resource if possible and not have a hybrid of both if possible. Thanks.

Categories

Resources