Properly initialize $scope - having error : "Expected undefined to be defined" - javascript

I need help, been searching and thinking for hours but didn't come up with a good solution. I am experiencing error "Expected undefined to be defined" which is repeatedly occurs when I call $scope in my It() functions.
Spec.js
describe("C0001Controller", function(){
var $scope,
$rootScope,
$injector,
$controller,
$httpBackend,
$loading,
C0001Controller;
describe("initialize controllers",function(){
beforeEach(function(){
angular.module('app.c0001App');
})
beforeEach(inject(function(_$rootScope_, _$injector_, _$controller_, _$httpBackend_, _$loading_)
{
$rootScope = _$rootScope_;
$injector = _$injector_;
$controller = _$controller_;
$httpBackend = _$httpBackend_;
$loading = _$loading_;
$scope = $rootScope;
C0001Controller = $controller('C0001Controller', {
$scope: $scope,
$loading : $loading
});
}));
});
it("should use the user ",function(){
var languages = [{id: "en", name: "English"}, {id: "jp", name: "Japanese"}];
expect(languages).toBeDefined();
it("should read if there are languages used", function(){
expect($scope).toBeDefined();
});
describe("checking connection to module and controller", function(){
it("should be connected to module", function(){
expect("app.c0001App.C0001Controller").toBeDefined();
});
it("contains C0001Spec Spec", function(){
expect(true).toBe(true);
});
it("should be equal to user", function(){
var user = {};
var c0001Data = user;
expect(c0001Data).toBe(user);
});
});
});
I was thinking if the format I did in the karma.conf.js file has a mistake.
// list of files / patterns to load in the browser
files: [
'node_modules/angular/angular.js',
'node_modules/angular-mocks/angular-mocks.js',
'app/*.js',
'tests/*.js'
],
here's my Controller.js
angular.module('app.c0001App', [
'ui.router'
])
.config(function($stateProvider) {
$stateProvider.state('/c0001', {
url : '/c0001'
, templateUrl : 'pages/C0001.html'
, data : {
pageTitle: 'LOGIN'
}
});
})
.controller('C0001Controller', function ($rootScope, $scope, $http, $window, $location, $loading) {
var promise = $http.get('changeLanguage.do?lang=en');
promise.success(function(data, status, headers, config) {
//some codes here
Thank you in advance.

Related

How do I stub `$window.localStorage` in my AngularJS unit tests?

angular.module('MyApp')
.controller('loginCtrl', function($scope, $rootScope, $location, $window, $auth) {
$scope.login = function() {
$auth.login($scope.user)
.then(function(response) {
if(response.data.users.status === 'success'){
$rootScope.currentUser = response.data.username;
$window.localStorage.user = JSON.stringify(response.data.users);
$location.path('/');
}
}).catch(function(response){
if(response.data.users.status === 'error'){
$scope.error = response.data.users.error;
}
})
};
});
I get the error:
users is undefined error
when testing above code with Karma and Jasmine.
The spec is below:
describe('LogController', function() {
var $scope, controller, $location, $window;
beforeEach(module('MyApp'));
beforeEach(inject(function($rootScope, $controller, _$location_ , _$window_ , _$httpBackend_) {
$scope = $rootScope.$new();
$window = _$window_
$httpBackend = _$httpBackend_;
$location = _$location_;
controller = $controller('loginCtrl', {
$scope: $scope,
$location: $location,
$window: $window
});
}))
it('should log in a user and redirect to homepage', function() {
$httpBackend.when('POST','/user/auth').respond(200);
//whitelist all view
$httpBackend.whenGET(/partials.*/).respond(200, '');
$scope.username = 'test';
$scope.password = '123456';
$scope.login();
$httpBackend.flush();
$scope.$apply();
expect($location.path()).toBe('/x');
});
})
What is users undefined? And how do I mock out a response from $window.localStorage so it won't be?
Youshould mock the response for login
$httpBackend.when('POST','/user/auth').respond(200, mockResponseData);
where:
mockResponseData = {
"data": {
"username": "someValue",
"users": {
"status": "success"
}
}
}

How to test $http with Jasmine in AngularJS

I'm trying to test the data received from an $http request in my controller.
I don't have too much experience testing with Angular so I'm struggling to under stand how to do it.
$scope. always comes back undefined and when I've tried fetching the data from the test, that seems to fail also. What am I missing?
Controller:
'use strict';
var myApp = angular.module('myApp.view1', ['ngRoute']);
myApp.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/view1', {
templateUrl: 'view1/view1.html',
controller: 'View1Ctrl'
});
}]);
myApp.controller('View1Ctrl', [
'$scope',
'$http',
function($scope, $http) {
$http.get('view1/data.json')
.then(function(res){
$scope.data = res.data.data
});
}]);
Test:
'use strict';
describe('myApp.view1 module', function() {
beforeEach(module('myApp.view1'));
describe('view1 controller', function(){
var scope, testCont;
beforeEach(inject(function($rootScope, $controller) {
scope = $rootScope.$new();
testCont = $controller('View1Ctrl', {$scope: scope});
}));
it('should....', function(){
expect($scope.data).toBeDefined();
});
});
});
The HTTP requests will not fire unless you call $httpBackend.flush().
More information can be found here: http://docs.angularjs.org/api/ngMock.$httpBackend
Test:
'use strict';
describe('myApp.view1 module', function() {
var $httpBackend, $rootScope, createController, jsonHandler;
beforeEach(module('myApp.view1'));
describe('view1 controller', function(){
var scope, testCont;
beforeEach(inject(function($rootScope, $controller, $injector) {
// Set up the mock http service responses
$httpBackend = $injector.get('$httpBackend');
// backend definition common for all tests
jsonHandler= $httpBackend.when('GET', '/view1/data.json')
.respond({data: '[XXX,XXX,XXX]'});
// Get hold of a scope (i.e. the root scope)
$rootScope = $injector.get('$rootScope');
// The $controller service is used to create instances of controllers
var $controller = $injector.get('$controller');
createController = function() {
return $controller('View1Ctrl', {'$scope' : $rootScope });
};
}));
it('should....', function(){
$httpBackend.expectGET('/view1/data.json');
var controller = createController();
$httpBackend.flush();
});
});
});

AngularFire karma test never reaches promise callback

I have a controller that uses AngularFire's $firebaseObject.
When the controller initializes, it sets the reference to Firebase, and uses $loaded function to verify that data from Firebase is actually there. Here is a simplified code of the controller:
myModule.controller('VotingQuestionsCtrl', ['$scope', '$rootScope', '$firebaseObject',
function($scope, $rootScope, $firebaseObject) {
var baseRef = new Firebase("https://somefirebaserepo.firebaseio.com/pathtomyobjects"),
topicsRef = baseRef.child("topics");
var topics = $firebaseObject(topicsRef);
$scope.dataLoaded = false;
topics.$loaded().then(function() {
$scope.dataLoaded = true;
topics.$bindTo($scope, 'topics').then(function() {
//do some stuff
});
}, function(error) {
$scope.dataLoaded = true;
console.log("oh no!");
});
This controller works pretty good in real life. The problem is testing it with Karma. No matter what I tried, my test spec never reaches the callback for topics.$loaded (neither the success function nor the error function).
Here is the current state of my test spec:
describe('VotingQuestionsCtrl', function() {
var $controller, $scope, $rootScope, $firebaseObject, $stateParams, $q, baseRef, $timeout;
beforeEach(module('wsApp.controllers'));
beforeEach(inject(function ($injector) {
MockFirebase.override();
$controller = $injector.get('$controller');
$q = $injector.get('$q');
$rootScope = $injector.get('$rootScope');
$timeout = $injector.get('$timeout');
$scope = $rootScope.$new();
$firebaseObject = $injector.get('$firebaseObject');
$rootScope.user = {username: "user"};
$rootScope.selectedSim = {phase: "phase1"};
baseRef = new Firebase("https://somefirebaserepo.firebaseio.com/pathtomyobjects");
baseRef.set({topics: {simId: {phase1: "bla"}}, users: {}});
baseRef.flush();
}));
it('loads the controller', function(done) {
$controller('VotingQuestionsCtrl', {$scope: $scope, $rootScope: $rootScope, $firebaseObject: $firebaseObject});
$scope.$digest();
setTimeout(function() {
expect($scope.dataLoaded).toBeTruthy();
done();
}, 200);
});
});
I've tried all sorts of flushing, digesting, whatever... the test goes through the rest of the controller, but the async part just doesn't work.

Jasmine unit test failing with resolve values in controller

Before i started, i have followed the advice found here without any success: How can I test a controller with resolve properties in AngularJS?
Im my app.js, i have a simple resolve:
var app = angular.module('myApp', ['ui.router']);
app.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('index', {
url: '/index',
templateUrl: 'html/home.html',
controller: 'HomeController',
resolve: {
homeInfo: function() {
return {
subtitle : 'Welcome to tables, ladders and chairs'
};
}
}
})
And in my HomeController.js:
app.controller('HomeController', function($scope, srv1, srv2, homeInfo, $rootScope) {
$rootScope.$broadcast('brdSubtitle', homeInfo.subtitle);
});
My test:
describe('HomeController', function () {
var $rootScope, $scope, $controller, homeController;
beforeEach(module('myApp'));
beforeEach(inject(function (_$rootScope_, _$controller_) {
$rootScope = _$rootScope_;
$scope = $rootScope.$new();
$controller = _$controller_;
homeController = $controller('HomeController', {'$rootScope': $rootScope, '$scope': $scope, homeInfo: { subtitle : 'Welcome to tables, ladders and chairs' }});
}));
it('should exist', function() {
expect(homeController).toBeDefined();
});
it('should have a subtitle', function() {
expect(homeController.homeInfo.subtitle.text()).toBe('Welcome to tables, ladders and chairs');
});
});
Error is:
TypeError: homeController.homeInfo is undefined in /path/to/specs.js
You should try to mock the service value in a beforeEach, because apparently putting the value in the $controller parameter does not work.
beforeEach(module(function($provide) {
$provide.value('homeInfo', {
subtitle : 'Welcome to tables, ladders and chairs'
});
}));
That's right, you didn't do this.homeInfo = homeInfo; in controller, and homeController.homeInfo should be undefined in this case.
There's no reason why mocked homeInfo local dependency should be tested. Test what happens in controller instead:
beforeEach(inject(function (_$rootScope_, _$controller_) {
...
brdSubtitleListener = jasmine.createSpy('brdSubtitleListener');
$scope.$on('brdSubtitle', brdSubtitleListener);
homeController = $controller('HomeController', {'$rootScope': $rootScope, '$scope': $scope, homeInfo: { subtitle : 'Welcome to tables, ladders and chairs' }});
}));
it('should broadcast a subtitle', function() {
expect(brdSubtitleListener).toHaveBeenCalledWith(jasmine.any(Object), 'Welcome to tables, ladders and chairs');
});

TypeError: undefined is not a function Angularjs

I've a unit tests that's keep failing with the error above not sure what exactly is wrong with this, by the looks of the error, its says that I need to declare a function. Can someone point me what is wrong with my code please:
unit test
describe('Test loginService', function() {
var $location, loginService, $scope, authentication, $rootScope;
beforeEach(function() {
module('app');
inject(function(_$location_, _$rootScope_, _loginService_,
_authentication_) {
$location = _$location_;
authentication = _authentication_;
loginService = _loginService_;
$rootScope = _$rootScope_;
$scope = $rootScope.$new();
});
});
it('Should successfully login with correct credentials', function() {
$scope.username = 'a#a.com';
$scope.password = 'a';
spyOn($location, 'url');
loginService.login($scope);//Complains about this line
expect($location.url).toHaveBeenCalled();
expect($location.url).toHaveBeenCalledWith('/home');
});
login service
app.factory('loginService', function(parserService, $location,
authentication, $rootScope) {
return {
login : function(scope) {
parserService.getData().then(function(data) { //This line
if (scope.username === data.username
&& scope.password === data.password) {
...
$location.url("/home");
} else {
scope.loginError = "Invalid Credentials";
}
});
}
});
Json file reader service
app.factory('parserService', function($http, $q) {
return {
getData: function() {
var deferred = $q.defer();
$http.get('res/file.json').success(function(data) {
deferred.resolve(data);
}).error(function(){
deferred.reject();
});
return deferred.promise;
}
}
});
error log
Chrome 36.0.1985 (Windows 7) Test loginService Should successfully login with correct credentials FAILED
TypeError: undefined is not a function
at Object.login (D:../js/services/loginService.js:6:18)
at null.<anonymous> (D:/../test/unit/loginTest.js:92:16)
since you can't format a comment, I'm using an answer... :D
have you tried this?
var $location, loginService, $scope, authentication, $rootScope, parserService;
beforeEach(function() {
module('app');
inject(function(_$location_,
_$rootScope_,
_parserService_,
_loginService_,
_authentication_) {
$location = _$location_;
authentication = _authentication_;
loginService = _loginService_;
$rootScope = _$rootScope_;
$scope = $rootScope.$new();
parserService = _parserService_;
});
});

Categories