Unit testing $httpBackend angular no response defined - angularjs

I'm struggling in my first test so please bear with me.
I want to test a function that make a http post:
$scope.formData= 'client=' + $scope.client_selected + '&version=' + $scope.version_selected + '&modules=' + $scope.client.modules;
var response = $http.post('http://localhost:8080/mavenproject8/lol/form', $scope.formData);
response.success(function (data, status, headers, config) {
$scope.validity = true;
$scope.status = "true";
});
response.error(function (data, status, headers, config) {
$scope.status = "false";
alert("Exception details: " + JSON.stringify({data: data}));
and my test looks like this:
...
beforeEach(inject(function ($injector) {
// Set up the mock http service responses
$httpBackend = $injector.get('$httpBackend');
$httpBackend.when('POST', 'http://localhost:8080/mavenproject8/lol/form', data)
.respond([200, {success: true, errors: [{}]}]);
and this is the it block:
it('should succeed when everything is correct', function () {
$rootScope.client.modules=["360"];
$rootScope.version_selected="2.4.0"
$rootScope.client_selected="NSM";
$rootScope.formData='client=' + $rootScope.client_selected + '&version=' + $rootScope.version_selected + '&modules=' + $rootScope.client.modules;
$httpBackend.expectPOST('http://localhost:8080/mavenproject8/lol/form',$rootScope.formData);
$rootScope.myFunc();
expect($rootScope.validity).toBe(true);
});
But this test doesn't pass, with the error:
Error: No response defined !
I feel like I'm so close but I can't make it work. I would be grateful if you could help me. Thank you!

Actually, your expected post request doesn't specify a response, that's why you see that error, so all what you have to do is:
$httpBackend.expectPOST('http://localhost:8080/mavenproject8/lol/form').respond(200,{});
//don't forget to make the flush after the function call.!!
$rootScope.myFunc();
$httpBackend.flush();
( you can dont need the $httpBackend.whenPost because that's useful when you want to create a back end definition, and specify the response( get case for example) so you can remove it, and your test will still pass.)

Related

Avoiding http error 405 while executing an put command with angularjs

First to say, when I enter the put command in POSTMAN (its then a POST there) I have no problems. Trying to execute the PUT command in code I receive a http 405 error.
The exact error is:
<p>Problem accessing /api/portfolio/createTransaction. Reason:
<pre> Method Not Allowed</pre></p><hr>
This is my code:
const app = angular.module('demoAppModule', ['ui.bootstrap']);
const apiBaseURL = "/api/portfolio/";
console.log(apiBaseURL);
app.controller('DemoAppController', function($scope, $http) {
const demoApp = this;
demoApp.createTransaction = function () {
console.log("Initiating createTransaction...")
var transactionDetails = $.param({
Reference: $scope.reference,
Quantity: $scope.quantity,
TradeDate: $scope.tradeDate,
});
const createTransactionURL =
apiBaseURL
+ "createTransaction";
console.log("Executing flow");
console.log("Transaction URL = " + createTransactionURL);
console.log("Transaction Details = " + transactionDetails);
$http.put(createTransactionURL, angular.toJson(transactionDetails))
.then(function (transactionDetails, status, headers){
$scope.ServerResponse = transactionDetails;
})
.catch(function (transactionDetails, status, header, config) {
$scope.ServerResponse = htmlDecode("transactionDetails: " + transactionDetails +
"\n\n\n\nstatus: " + status +
"\n\n\n\nheaders: " + header +
"\n\n\n\nconfig: " + config);
});
};
});
Appreciate any help!
The server is rejecting your request, likely because it doesn't allow PUT requests.
It's probably expecting a HTTP POST instead of a PUT.
If so, change $http.put to $http.post - the method signatures are identical.
If you think the server should be accepting a PUT, you'll need to check why the server side code is rejecting it, which won't be apparent in the client code

Synchronous AngularJS $http Call

I have an service in my Angular app that is responsible for authorizing the user and returning the auth token back.
However, due to the async nature of $http, I cannot properly isolate the logic of my service. Instead I must return a promise and push the logic of interpreting the response to the caller of the service (single responsibility red flag).
Given this, it's made me reconsider whether I am thinking about this correctly. I come from a Java world where the majority of interactions are synchronous, so something isn't sitting well with me as I try to architect a clean design with single responsibility.
What am I missing here?
UPDATE
I realize the below will not work as intended, but that's my thought of how I'd like it to work at least:
app.service('AuthenticationService', ['$http', '$httpParamSerializerJQLike', function($http, $httpParamSerializerJQLike)
{
this.authServerBaseURL = "...";
this.clientId = "...";
this.authenticate = function(username, password)
{
var config =
{
headers:
{
"Content-Type" : 'application/x-www-form-urlencoded',
"Authorization" : "Basic " + btoa(this.clientId + ":")
}
}
var body = $httpParamSerializerJQLike(
{
grant_type : "password",
username : username,
password : password
});
return $http.post(this.authServerBaseURL + '/oauth/token', body, config).
success(function(data, status, headers, config)
{
return data.access_token;
}).
error(function(data, status, headers, config)
{
return false;
});
}
}]);
Update after you added code: Your thought process can work, see below. However, $http docs say not to use .success and .error. If you instead use .then, as in my examples below, it will work.
Assuming your code is something similar to this:
// AuthService
this.authenticate = function() {
return $http.post('http://example.com', body, config);
}
// Using it:
AuthService.authenticate().then(function(data) {
var token = data.access_token;
});
You can move the knowledge about how the data is extracted to the service like this:
// AuthService
this.authenticate = function() {
return $http.post('http://example.com', body, config).then(function(data) {
return data.access_token;
});
}
// Using it:
AuthService.authenticate().then(function(token) {
var token = token;
});
what happens here is that you make a new promise by calling .then on the $http promise, which is what is returned. The promises are chained, so the $http promise will resolve this new promise, which then resolves itself with the extracted token.

How do I use $resource to post to a web-service?

I'm not very good with angular. I want to post to a web service, sending some xml with my search parameters. I don't want to send the parameters in the query string. I've read the official documentation, but I'm still confused. I'm mostly hung up on how to define the $resource to be able to post the way I want.
The error I get is: POST 'https://someWebservice/searchnet'::ERR_INSECURE_RESPONSE
My code is below:
'use strict';
angular.module('app').controller('inventorySearchController', inventorySearchController);
inventorySearchController.$inject = ['$scope','$http', '$resource'];
function inventorySearchController($scope, $http, $resource) {
console.log("controller initialized...");
$scope.callService = function(){
console.log("callService function called...");
var urlSearchService = 'https://someWebservice/search';
var skuVal = $scope.skuField;
var mVenVal = $scope.mVendorField;
//need to somehow specifiy that xml is a #FormParam
var xmlItemSearchRequest = "<ItemSearchRequest>"
+"<skuid>" + skuVal + "</skuid>"
+"<mvendor>" + mVenVal + "</mvendor>"
+"</ItemSearchRequest>";
console.log('calling: ' + urlSearchService + 'sending xml: ' + xmlItemSearchRequest);
var Results = $resource(urlSearchService, {
save: {
method: 'POST',
isArray: true
}
});
var result = Results.save();
console.log('Results: ' + Results);
console.log('result: ' + result);
var successfunction = function(){
$scope.searchResults = data;
console.log('call to ' + urlSearchService + ", was a success.");
};
var errorfunction = function(){
console.error('Calling error', status, data);
};
};
};
The error shown is not about how you posted data. Instead, response was not signed by a valid SSL certificate (or the certificate could not be accepted). That is due to the use of HTTPS protocol. You should consider using HTTP instead.
You can try the approach suggested here to confirm that this is the case.

Unexpected Request Error with $HttpBackend (AngularJS)

I am using HttpBackend to mock some Http responses for some calls that my Angular app is making.
However, I am getting the error "Unexpected Request: [object Object] undefined" when I run my tests.
I know that usually this error means you're missing or mistyped one of the $http requests that the app makes so it can't find a response. But my error is not specific like the other ones which usually say like "Unexpected Request: GET api/call" so I don't know what is wrong.
Has anyone ever encountered this specific error before?
Sample Code
angular controller:
app.controller( 'ctrl',
[ '$scope' , '$http' , '$location', function( $scope, $http, $location ) {
$http.get(
"/api/1.0/id/" + id,
{
headers: getAuthHeaders()
}
).success(function( data ){ //... })]
);
jasmine test:
it('should ...', function(){
httpBackend.whenGET('/api/1.0/id/*').respond(200,{"test":"Test"});
//...
});
I tried your code and test by myself. I add a function to set the ID, but I think you have something simular:
//PRESET ID
var id = 'deajedgwe1e213df';
//FUNCTION TO CAPSULATE API CALL
this.callApi = function () {
http.get(
"/api/1.0/id/" + id,
{
//headers: getAuthHeaders()
}
).success(function( data ){
console.log('success', data);
}).error(function (err) {
console.log('error', err);
});
};
//FUNCTION TO SET ID
this.setId = function (ID) {
id = ID;
};
then I copied your test and modified it like this:
it('should ...', function(){
ctrl.setId('test123ID');
httpBackend.expectGET('/api/1.0/id/test123ID').respond(200,{"test":"Test"});
ctrl.callApi();
httpBackend.flush();
httpBackend.verifyNoOutstandingExpectation();
httpBackend.verifyNoOutstandingRequest();
});
this works. alternative you could do this:
it('should ...', function(){
httpBackend.expectGET(/api/i).respond(200,{"test":"Test"});
ctrl.callApi();
httpBackend.flush();
httpBackend.verifyNoOutstandingExpectation();
httpBackend.verifyNoOutstandingRequest();
});
this works too, but it only verifies, that /api has been called... I don't if this is that, what you want to test.
I think the major problem is your asterisk notation at the api-call. try to modify your code like mine. if this shouldn't help, you should have a call on your header function.
Good luck.

angular jsonp factory doesn't work

I have this factory in angular, and its returning me a 0 error code always, even tho i can see it fetches from the json origin, can someone help me?
app.factory('docFactory', function($http) {
var docFactory = {
async: function(page) {
var url = 'http://example.com/ProviderRequest?&queryString=searchv2&callback=JSON_CALLBACK';
var promise = $http.jsonp(url).error(function (response, status) {
alert(status);
}).success(function (response, status) {
alert(status);
}).then(function (response, status) {
return response.data;
});
return promise;
}};
return docFactory;
});
I ran into this myself. If your JSONP is a function call or something falsy (null, false, undefined) you will encounter this behavior. Take a look at this code from AngularJS HTTP backend for more info (lines 41 - 54 are relevant).
If you are returning a function, you might just need to return true or something after the call.
Edit: After looking at your plunker it seems that your JSONP response is not calling the callback method. The response should be angular.callbacks._0( { ... } ); where { ... } is your object, and angular.callbacks._0 is the value of the callback query parameter in the request.
Your example above is almost right. Just change the callback parameter to
jsoncallback=JSON_CALLBACK
You should have something like that at the end
$http.jsonp(url + '?jsoncallback=JSON_CALLBACK').success(function(data) {
console.log(data);
})

Resources