AngularJS testing $httpBackend.whenGET().respond() not working with number as parameter - angularjs

This test:
it("getFooCount success", function () {
httpBackend.whenGET('/api/getFooCount').respond(1);
fooService.getFooCount();
httpBackend.flush();
expect(fooService.FooCount).toBe(1);
});
fails: "Expected null to be 1"
(fooService.fooCount is null before the api get method is called).
Yet this test passes:
it("getFooCount success", function () {
httpBackend.whenGET('/api/getFooCount').respond("1");
fooService.getFooCount();
httpBackend.flush();
expect(fooService.fooCount).toBe("1");
});
It seems to be able to pass the test with anything (an object, string, array, etc) EXCEPT a number in the .respond().
The api I am calling just returns an integer, any advice as to how I can get this to work, and/or why it is failing?

Have a look at the API for respond, because the first argument is actually the status code.
Try instead respond(200, 1).
Angularjs seems to smart its way around when you provide a non statist object as first parameter

Related

CucumberJs skipping step definition - maybe callback last parameter in step definition?

I just started working with cucumberJs, gulp and protractor for an angular app and noticed, luckily as all my steps were passing, that if you don't pass in and use that 'callback' parameter in the step definition, cucumberJs might NOT know when this step is completed and will skip other steps and mark them all as 'passed'
Below is an example from the cucumberJs doc: https://github.com/cucumber/cucumber-js
Example 1:
this.Given(/^I am on the Cucumber.js GitHub repository$/, function (callback) {
// Express the regexp above with the code you wish you had.
// `this` is set to a World instance.
// i.e. you may use this.browser to execute the step:
this.visit('https://github.com/cucumber/cucumber-js', callback);
//
The callback is passed to visit() so that when the job's finished, the
next step can
// be executed by Cucumber
.
});
Example 2:
this.When(/^I go to the README file$/, function (callback) {
// Express the regexp above with the code you wish you had.
Call callback() at the end
// of the step, or callback(null, 'pending') if the step is not yet implemented:
callback(null, 'pending');
});
Example 3:
this.Then(/^I should see "(.*)" as the page title$/, function (title, callback) {
// matching groups are passed as parameters to the step definition
var pageTitle = this.browser.text('title');
if (title === pageTitle) {
callback();
} else {
callback(new Error("Expected to be on page with title " + title));
}
});
};
I understand you have 2 choices here:
a. Either you return a promise and don't pass the call back OR
b. You pass in the callback parameter and call it whenever the step definition is complete so cucumberJs knows to return and go to next step or next scenario.
However, I tried both above and still running into a weird situation where the top two scenarios will work NORMALLY as you would expect, but the third and fourth scenario within that same feature file will be skipped and all passed.
Is there anything special to consider about features with more than 2 scenarios?
As long as I have <= 2 scenarios per feature files, everything works fine, but the moment I had a third scenario to that feature file, that third scenario is ignored and skipped.
Any ideas?
Without seeing your actual steps I can't say for sure but it sounds like an asynchronous issue or dare I say it, a syntax error in the scenario. Have you tried changing the order of the scenarios to see if that has an impact.

$q.all returns only 1 object (angular ionic app)

I have the following function:
$q.all([Timeline.allEvents($http),
Timeline.allTimeSlots($http)]).then(function (returnValues) {
Timeline.constructedTotalTimeline(returnValues)
});
The Timeline.construcedTotalTimeline should be called with the results of both async calls. The function only receives the first object however (the one returned by Timeline.allEvents).
What am I missing here?

Angular JS-Jasmine how to unit test $location.path().search()?

been doing some googling but cant find an answer to this little problem of mine. Just trying to test this bit of code from my controller:
$scope.viewClientAssets = (id) ->
$location.path("/assets").search("client_id", "#{id}")
which in turn returns this url:
http://localhost:3000/admin#/assets?client_id=19
this all works fine however when unit testing......A few assumptions:
I have my spec set up correctly as I have other tests and expectations working perfectly fine so here is the test:
it 'checks if view client assets path is correct', ->
createController()
#gets rid of unnecessary function calls
flushRequests()
#calls the ctrl function with necessary args
$scope.viewClientAssets(clientData.client.id)
spyOn($location, 'path')
spyOn($location, 'search') #tried diff methods here such as
# and.returnValue(), .calls.any(), calls.all()
expect($location.path).toHaveBeenCalledWith("/assets")
expect($location.path.search).toHaveBeenCalled()
all other tests pass however when this gets hit I get the following error:
TypeError: Cannot read property 'search' of undefined
the console debugger tells me:
$scope.createClientAsset = function(id) {
return $location.path('/assets/create').search("client_id", "" + id);
};
that path is undefined?
any ideas anyone?
To test the spyOn, for search, do the following
spyOn($location, 'path').and.callThrough();
spyOn($location, 'search');
That will return values correctly.
You are spying on $location.path and not returning anything, or returning undefined.
Make your spy return a string (the string you would normally expect, the actual path) and the search function, defined for all strings in javascript, will work normally in your test.
e.g. Do as follows:
spyOn($location, 'path').and.returnValue('/client_id/')
$location.path('anything'); // returns '/client_id/'

protractor do all API functions really return promises?

When I ran this test:
browser.get('http://www.valid-site.com').then(function(msg){
console.log(msg);
});
I'm expecting 1 or true to be printed to indicate that the operation is successful since get() should return a promise with the value it has been resolved to. Instead it prints 'null'. In the API docs http://angular.github.io/protractor/#/api there is no indication of a return type. I'm confused which functions return a promise and which do not.
Not sure if it would directly answer the question, but, if you look into the browser.get() protractor's implementation (it wraps the WebDriverJS's driver.get()), you can see that it returns:
return this.executeScript_(
'angular.resumeBootstrap(arguments[0]);',
msg('resume bootstrap'),
moduleNames);
And since the executed script has no return, this is the reason you see null resolved.
But, if you look into, for example, browser.refresh() implementation, you'll see that it returns:
return self.executeScript_(
'return window.location.href',
'Protractor.refresh() - getUrl').then(function(href) {
return self.get(href, timeout);
});
In this case, the executed script returns window.location.href value, which you would see on the console in case:
browser.refresh().then(function (url) {
console.log(url);
});
I guess, you can understand this "Read the source, Luke" answer, as, whenever you are not sure, look into sources.

How to mock get(id) requests

I am building an application prototype and try to mock the REST web-services.
Here is my code:
var mock = angular.module('mock', ['ngMockE2E']);
mock.run(function($httpBackend){
users = [{id:1,name:'John'},{id:2,name:'Jack'}];
$httpBackend.whenGET('/users').respond(users);
$httpBackend.whenGET(new RegExp('\\/users\\/[0-9]+')).respond(users[0]);
}
Everything is ok, my resource User.query() returns all users, and User.get({id:1}) and User.get({id:2}) returns the same user (John).
Now to improve my prototype, I would like to return the appropriate user, matching the good id.
I read in the angular documentation I should be able to replace the RegExp URI by a function. The idea is to extract the id from the url to use it in respond method.
I then tried this:
$httpBackend.whenGET(new function(url){
alert(url);
var regexp = new RegExp('\\/users\\/([0-9]+)');
id = url.match(regexp)[1];
return regexp.test(url);
}).respond(users[id]);
The problem is the url parameter is always undefined. Any idea to achieve my goal?
By using new function(url) your app tries to instantiate a new object from your anonymous function and pass that new object as the first argument of the $httpBackend.whenGET() call.
Of course, at the time of calling whenGET() no URL is provided, thus it is always undefined.
You should pass the function itself (and not an object instanciated using the function). E.g.:
$httpBackend.whenGET(function (url) {
...
}).respond(users[id]);
UPDATE:
After some more digging it turned out that the option to pass a function as the first argument to whenGET was added in version 1.3.0-beta.3. The docs you were reading probably referred to the latest beta version, while you were using an earlier version.
(Note that even versions 1.3.0-beta.1 and 2 did not provide this option.)
Without getting into much detail, responsible for verifying a matching URL is MockHttpExpectation's matchUrl method:
function MockHttpExpectation(method, url, data, headers) {
...
this.matchUrl = function(u) {
if (!url) return true;
if (angular.isFunction(url.test)) return url.test(u);
if (angular.isFunction(url)) return url(u); // <<<<< this line does the trick
return url == u;
};
The line if (angular.isFunction(url)) return url(u); is the one that gives the option to directly pass a function and was added in version 1.3.0-beta.3 (as already mentioned).
But, if you still want to pass a function to a previous AngularJS version, you could "trick" angular into believing you passed a RegExp, by providing an object with a test method.
I.e. replace:
.whenGET(function (url) {...})
with:
.whenGET({test: function (url) {...}})
See, also, this short demo.
I found a solution by using a function in the respond part instead of the when part:
$httpBackend.whenGET(new RegExp('\\/users\\/[0-9]+')).respond(
function(method, url){
var regexp = new RegExp('\\/users\\/([0-9]+)');
var mockId = url.match(regexp)[1];
return [200, users[mockId]];
}
});

Resources