I am working on a code that has some unit test failing which I am trying to run. The unit test is
it('opens a confirmation dialog when deleting a layer and calls the delete wizard', function () {
var numLayers = scope.service.layers.length;
scope.deleteLayer({
serviceName: 'service1',
layerName: 'testLayer'
});
//Make sure confirmation dialog has been called
expect(bootbox.confirm).toHaveBeenCalled();
//the layer is NOT removed from the list
expect(scope.service.layers.length).toBe(numLayers);
});
I keep getting the error:
Unexpected request Get /api/configuration/utilities/userpreferences/f=json
I am trying to create a spyon for taking care of this api call. I am using this
spyOn(resourceFactory.configuration.utilities.userpreferences, 'get').and.callFake(function () { });
I have also defined this in the describe scope and injected in beforeeach
var resourceFactory = {
configuration: {
utilities: {
userpreferences: {
get: function () { }
}
}
}
};
The thing is I dont care about this call to API since I am not testing it.
When I use $httpBackend and do the following
/$httpBackend.whenGET("/api/configuration/utilities/userpreferences?f=json").respond({});
it works but I am not sure if this is the right way to do it. Especially since its not used anywhere else in the project.
Can you help with this.
Related
I have a service Home and inside it, I have selectInterval function like so:
Home.selectInterval = function () {
var interval = $interval(function () {
if (angular.element('.ui-select-toggle').length > 0) {
angular.element('.ui-select-toggle').bind('click', function () {
if (angular.element('.ui-select-choices-row').length > 0) {
angular.element('.ui-select-choices-group').mCustomScrollbar();
}
});
$interval.cancel(interval);
}
}, 50);
};
Right now I am testing it like this:
it('selectInterval() should be called.', function () {
Home.selectInterval();
$interval.flush(50);
$rootScope.$apply();
expect(Home.selectInterval).toHaveBeenCalled();
// need to test $interval as well
});
I want to test if function is called and also $interval worked fine. Right now It giving me this error.
Some of your tests did a full page reload!
I'm not sure if this test is what is causing your issue. Whenever I have seen that error it is because there is some code that is changing the url. Setting something like $window.location.href or $location.path('/new-path') will cause the phantomjs browser to do a page reload which there just isn't any support to handle right now.
If you find this is the issue, you just need to try to spy the method and it will never actually call it. That specifically works for $location.path('/new-path')
I have a Typescript/Angular app that runs in an iframed window. In the app, I'm using the intl-tel-input module to format & validate our phone number inputs. Intl-tel-input puts 'intlTelInputUtils' functions on the $window object. When testing the app locally without the iframe, I was able to successfully call the methods like (note the surrounding window is just to satisfy the Typescript compiler:
(<any>window).intlTelInputUtils.getExtension(phoneNumber.userInput, phoneNumber.countryCode);
and get tests to pass by mocking the window.intlTelInputUtils object:
$window.intlTelInputUtils = {
'getExtension': function () { return ''; },
'formatNumber': function () { return ''; },
'isValidNumber': function () { return true; }
};
But of course this doesn't work once we're in the embedded iframe window. IntlTelInputUtils now appears at parent.window.intl....
I tried changing the method call to:
(<any>parent.window).intlTelInputUtils.getExtension(phoneNumber.userInput, phoneNumber.countryCode);
but I'm unable to push it to the server to see if that'll work (will it??) until I can get the Jasmine tests to pass. I tried changing the mock to:
$parent.$window = {
'intlTelInputUtils': {
'getExtension': function () {
return '';
},
'formatNumber': function () {
return '';
},
'isValidNumber': function () {
return true;
}
}
};
But I realize this isn't correct.
How do I correctly mock parent.window.intlTelInputUtils in my tests??
I'm not sure this will solve your problem but have you tried to add a spy to that specific call? For instance:
it('my test name', inject(function ($window) {
spyOn($window.intlTelInputUtils, 'getExtension');
...
}));
And ofc you need to ensure that you and use $window on your code and not window directly.
I'm writing a spec that checks a method is called during the config phase of the Angular module under test.
Here's a simplified look at the code being tested:
angular.module('core',['services.configAction'])
.config(function(configAction){
configAction.deferIntercept(true);
});
What happens above is we define a core module that has a single dependency.
Then, in the config-block of the core module, we call the deferIntercept method on the configAction object given to use from services.configAction.
I'm trying to test that core's config calls that method.
This is the current setup:
describe('core',function()
{
const configActionProvider={
deferIntercept:jasmine.createSpy('deferIntercept'),
$get:function(){
return {/*...*/}
}
};
beforeEach(function()
{
module(function($provide)
{
$provide.provider('configAction',configActionProvider);
});
module('core.AppInitializer');
inject(function($injector)
{
//...
});
});
it('should call deferIntercept',function()
{
expect(configActionProvider.deferIntercept).toHaveBeenCalledWith(true);
});
});
The problem with that is that it doesn't override configAction and so the spy is never called, the original method is.
It will do so if I remove it as a dependency of the core module, so angular.module('core',[]) instead of angular.module('core',['services.configAction']) will work and the spy is called.
Any idea how to override services.configAction during testing without removing it from the dependency list?
Have a look at - https://dzone.com/articles/unit-testing-config-and-run.
Something like the following -
module('services.configAction', function (configAction) {
mockConfigAction = configAction;
spyOn(mockConfigAction, 'deferIntercept').andCallThrough();
});
module('core');
in your beforeEach might do the job.
I'm trying to use Protractor's addMockModule to insert mock data in my end-2-end test.
My test is supposed to go to a web site, find a button by css-class and click it. The button click calls the function dostuff() in MyService, which fetches data from the backend.
My code so far:
describe('should display validation error', function () {
it('should work', function () {
browser.get('http://my.url');
browser.addMockModule('MyService', function () {
// Fake Service Implementation returning a promise
angular.module('MyService', [])
.value({
dostuff: function () {
return {
then: function (callback) {
var data = { "foo": "bar" };
return callback(data);
}
};
}
});
});
var button = element(by.css('.btn-primary'));
button.click();
browser.sleep(5000);
});
});
The test is accessing the web site and clicking the button. The problem is that real data from the database is displayed, not the mock data.
I followed several threads, like this one: How to mock angular.module('myModule', []).value() in Jasmine/Protractor
However, it seems like the function protractor.getInstance() is deprecated.
Anyone got this working?
Take a look at the unit test for addMockModule(). Try to add the addMockModule statement before you call browser.get()
https://github.com/angular/protractor/blob/673d416b7ef5abd0953da940cfa8cf2a59650df4/spec/basic/mockmodule_spec.js
I have start to learning how to test properly on controller and encounter this following script.
http://www.yearofmoo.com/2013/01/full-spectrum-testing-with-angularjs-and-karma.html
it('should have a properly working VideosCtrl controller', inject(function($rootScope, $controller, $httpBackend) {
var searchTestAtr = 'cars';
var response = $httpBackend.expectJSONP(
'https://gdata.youtube.com/feeds/api/videos?q=' + searchTestAtr + '&v=2&alt=json&callback=JSON_CALLBACK');
response.respond(null);
var $scope = $rootScope.$new();
var ctrl = $controller('VideosCtrl', {
$scope : $scope,
$routeParams : {
q : searchTestAtr
}
});
}));
I am a bit confused... expectedJSON is in the following API page:
https://docs.angularjs.org/api/ngMock/service/$httpBackend
I am confused Just wondering what's testing in here, i can see the describe there but still lost... what's expected here?
This test has no explicit assertions, but it will fail if constructing the controller instance throws an exception for any reason.
Remember that if an assertion is failed, it throws an exception. Test runners just run your test function like so:
try {
runTest();
} catch (e) {
markTestFailed(e);
}
So if your test code throws an exception for any reason, the test will fail.
As with any unit test, you arrange act and then assert.
For the above test, the parts of arrange and act are self evident but the assert part may not be obvious. The test is just verifying that the search request was send when controller was created.
If you look at the controller code for video controller
$youtube.query($scope.q, true, function(q, videos) {
$scope.videos = videos;
$scope.onReady();
});
this can be confirmed.
The assertion part is done by the $httpBackend.expectJSONP. This setup tells karma to verify that a GET request is made to a specific url. The url here is the google search api with the search term cars.
The test basically sets up a mock backend and asserts that it was called.