How to mock REST with angular without affecting templates - javascript

I am just trying out angular.
I want to get a list of items and show it in template, just hardcoded that now and want to see how it works with ajax. I dont have a rest server working and is trying to mock ajax call.
I just tried including angular mock e2e, but then looks like its covering get for templates as well and throws an error Error: Unexpected request: GET views/main.html
Is there a simple way I can just mock REST requests and have templates work with usual ajax?
This is not a unit-test or e2e test scenario, more of a back-end less development. I am doing this on main app and not in testing.
My app.js looks like this
'use strict';
var app = angular
.module('sabithangularApp', [
'ngResource', 'ngMockE2E'
]);
app.run(function ($httpBackend) {
var tasks = [{...},{....},{...}
];
$httpBackend.whenGET('/tasks').respond(tasks);
$httpBackend.whenGET(/^\/templates\//).passThrough();
//...
});
and error in console looks like
Error: Unexpected request: GET views/main.html
No more request expected
at $httpBackend (http://127.0.0.1:9000/bower_components/angular-mocks/angular-mocks.js:1177:9)
at sendReq (http://127.0.0.1:9000/bower_components/angular/angular.js:7967:9)
at $http.serverRequest (http://127.0.0.1:9000/bower_components/angular/angular.js:7708:16)
at wrappedCallback (http://127.0.0.1:9000/bower_components/angular/angular.js:11100:81)
at wrappedCallback (http://127.0.0.1:9000/bower_components/angular/angular.js:11100:81)
at http://127.0.0.1:9000/bower_components/angular/angular.js:11186:26
at Scope.$eval (http://127.0.0.1:9000/bower_components/angular/angular.js:12175:28)
at Scope.$digest (http://127.0.0.1:9000/bower_components/angular/angular.js:12004:31)
at Scope.$apply (http://127.0.0.1:9000/bower_components/angular/angular.js:12279:24)
at http://127.0.0.1:9000/bower_components/angular/angular.js:1382:15

You need to add an extra line of code (below all other .whenGET()'s) for this that ignores the mock e2e, something like this:
$httpBackend.whenGET(/.*/).passThrough();
This is a catch-all for any (get) request that is not matched by any other line.
EDIT:
the line below catches all requests starting with 'view/':
$httpBackend.whenGET(/^views\/.*/).passThrough();

As I know you need to use $httpBackend for testing.

Related

How to inject ngRoute into Jasmine / Karma AngularJS unit test?

I'm trying to get a basic unit test example working. It all works fine with this app.js
var whapp = angular.module('whapp', [])
.filter('reverse',[function(){
return function(string){
return string.split('').reverse().join('');
}
}]);
and this spec.js
describe('Filters', function(){ //describe your object type
beforeEach(module('whapp')); //load module
describe('reverse',function(){ //describe your app name
var reverse, rootScope;
beforeEach(inject(function($filter){ //initialize your filter
reverse = $filter('reverse',{});
}));
it('Should reverse a string', function(){ //write tests
expect(reverse('rahil')).toBe('lihar'); //pass
});
});
});
with this karma files config
files: [
'node_modules/angular/angular.js',
'node_modules/angular-mocks/angular-mocks.js',
'node_modules/angular-mocks/angular-route/angular-route.js',
'node_modules/angular-mocks/angular-ui-router/release/angular-ui-router.js',
'app/js/*.js',
'tests/*.js'
]
The problem occurs when I try to inject ngRoute into my module in app.js like so
var whapp = angular.module('whapp', ['ngRoute'])
.filter('reverse',[function(){
return function(string){
return string.split('').reverse().join('');
}
}]);
In which case I get the following error in karma [UPDATE: this error occurs even if I don't load the angular-mock.js library into karma as shown above]
TypeError: undefined is not a constructor (evaluating 'reverse('rahil')') in tests/spec.js (line 9)
So... how do I inject ngRoute into spec.js correctly? I've tried a variety of things, none of which worked.
Apparently, you get this error because PhantomJS fails to instantiate your main Angular module whapp. One possible reason is, that the file node_modules/angular-mocks/angular-route/angular-route.js is missing.
Obviously, you are using npm to manage your dependencies. So try to replace your current file with:
node_modules/angular-route/angular-route.js
The same for the ui-route module:
node_modules/angular-ui-router/release/angular-ui-router.js
I hope this will help you.

How to debug this angular js code?

When errors happen inside of angular, debugging seems impossible for me. I have this code:
<script>
var my_app = angular.module("campaign_listing", ['$http']);
var controllers = {};
controllers.campaign_list_controller = function($http){
var filters = {};
var campaigns = {};
this.update_fields = function(){
console.log("update!");
}
}
my_app.controller(controllers);
</script>
And it throws this error:
angular.js:38Uncaught Error: [$injector:modulerr] http://errors.angularjs.org/1.4.6/$injector/modulerr?p0=campaign_listing&p1…ogleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.4.6%2Fangular.min.js%3A19%3A463)
And without the minified version:
Uncaught Error: [$injector:modulerr] Failed to instantiate module campaign_listing due to:
Error: [$injector:modulerr] Failed to instantiate module $http due to:
Error: [$injector:nomod] Module '$http' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
http://errors.angularjs.org/1.4.6/$injector/nomod?p0=%24http
I'm not using routing, so that link actually confuses me.
Can someone tell me what the problem is and how to debbug this in the future?
You could create a breakpoint in the line of my_app.controller() and step into the Angular code (good luck, that's hard for beginners).
Only from reading your code, I suggest to try this:
<script>
var my_app = angular.module("campaign_listing", []);
var campaign_list_controller = function($http){
var filters = {};
var campaigns = {};
this.update_fields = function(){
console.log("update!");
}
}
my_app.controller('campaign_list_controller', campaign_list_controller);
</script>
I suppose you might get even more problems later, because this all doesn't look much like typical Angular code. My advise: try to exercise with the Tutorial first.
The previous answer is correct but this is can also happen when you do NOT include a Controller file. Example below shows at line 60 I had commented out the controller file but at line 13 I was actually referencing a AppCtrl. If I uncomment the line 60 the error goes away.
Here is what you would get on console:

AngularJS testing $httpBackend.flush() causes error

I'm trying to do some testing with jasmine for an AngularJS service that I have been creating for Spotify. But I keep getting an error with my tests when testing promises.
My test is currently like this:
describe('Spotify.search', function () {
var $httpBackend;
var $rootScope;
var Spotify;
var api = 'https://api.spotify.com/v1';
beforeEach(inject(function(_Spotify_, _$httpBackend_, _$rootScope_) {
Spotify = _Spotify_;
$httpBackend = _$httpBackend_;
$rootScope = _$rootScope_;
jasmine.getJSONFixtures().fixturesPath='base/test/mock';
}));
it('should return an array of artists', function () {
$httpBackend.when('GET', api + '/search?q=Nirvana&type=artist').respond(
getJSONFixture('search.artist.json')
);
Spotify.search('Nirvana', 'artist').then(function (data) {
expect(data).toBeDefined();
expect(data.artists.items.length).toBeGreaterThan(0);
});
$httpBackend.flush(); //This line causes the error
});
});
and the error that comes out is:
✗ should return an array of artists
TypeError: 'undefined' is not a function (evaluating '$browser.$$checkUrlChange()')
at /Users/XXXX/Work/angular-spotify/bower_components/angular/angular.js:12502
at /Users/XXXX/Work/angular-spotify/bower_components/angular-mocks/angular-mocks.js:1438
at /Users/XXXX/Work/angular-spotify/test/spec/angular-spotify.spec.js:249
Line 249 is $httpBackend.flush()
I'm using karma-jasmine and running tests through PhantomJS.
AngularJS: 1.2.24
angular-mocks: 1.2.16
angular-scenario: 1.2.16
karma-jasmine: 0.2.0
Why would $httpBackend be trying to change the url in the browser?
Any help on this would be great.
The problem is your version mismatch between Angular and Angular-Mocks. This line was added recently in Angular-Mocks:
https://github.com/angular/angular.js/blob/v1.2.24/src/ngMock/angular-mocks.js#L59
I could fix this by pushing both Angular and Angular-Mocks to 1.2.22 where this change is not present yet in both projects. But I guess 1.2.24 for both would also work.
The flush method is part of the mocked httpBackend implementation.
See :
https://github.com/angular/angular.js/blob/master/src/ngMock/angular-mocks.js#L1823
To use this implementation of HttpBackend you need to inject 'ngMockE2E' in your dependencies.

Angular code mangled causes "Unknown Provider" message

I want to mangle my AngularJS file, and it works for almost the whole part. However, when I click through the app and navigate to the only part that uses ngLazyBind and angular-history, I get the following issue: Error: [$injector:unpr] Unknown provider: aProvider <- a <- $lazyBind .
I am using ngMin in hopes that this kind of stuff wouldn't happen. When I set uglify's mangled property to false, this issue goes away.
Another little note - injecting $lazyBind into a controller is what causes the error. I can include lazyBind in the app without issue, but when I inject $lazyBind into a controller the error arises.
The reason I mention angular-history is if I completely eliminate lazyBind, the exact same error appears with Error: [$injector:unpr] Unknown provider: mProvider <- m <- History.
It doesn't look like the 2 libraries are minification-safe...
In angular-history line 88...
angular.module('decipher.history', ['lazyBind']).service('History',
function ($parse, $rootScope, $interpolate, $lazyBind, $timeout, $log,
From the error message, it looks like $parse was renamed to m and angular wasn't able to resolve it.
Same thing with ngLazyBind line 89...
app.factory("$lazyBind", lazyBindProvider);

Compiling AngularJS app with animation module in yeoman gives unknown provider error

Im having trouble compiling an angular app that uses the new animation service in Yeoman. Im using the yo angular:app generator.
Everything is fine when working uncompiled but as soon as I run grunt build. Once compiled an unknown provider error is given when I run the DIST folder. I believe it is because the animation service requires a class name, not a normal name. Anyone come across this or a fix?
I tried the usual dependancy rename so the compiler respects the naming but no luck.
Case 1:
angular.module('App', ['ngAnimate']).animation('.pageCube', function(){
// animation stuff
});
Error: [$injector:unpr] Unknown provider: aProvider <- a <- .pageCube-animation
Case 2:
angular.module('App', ['ngAnimate']).animation('.pageCube', ['.pageCube', function(){
// animation stuff
}]);
Error: $injector:unpr] Unknown provider: .pageCubeProvider <- .pageCube <- .pageCube-animation
Case 3: (never going to work but Provider is found)
angular.module('App', ['ngAnimate']).animation('pageCube', ['pageCube', function(){
// animation stuff
}]);
Error: [$animate:notcsel] Expecting class selector starting with '.' got 'pageCube'.
Notes
I am using: AngularJS v1.2.0-rc.2 which is further along than what yo angular:app installs. This might be something to keep in mind in the future.
Case 2 and 3 are completely wrong, the string after the [ is mainly needed as minify-safe option to function parameters so you would need a pageCube parameter on the function, but since you're far from this approach I guess you're doing something wrong inside the function

Categories