Tuesday, 15 January 2013

javascript - How to unit test functions with $http.jsonp in AngularJS? -



javascript - How to unit test functions with $http.jsonp in AngularJS? -

here part of controller:

$scope.isloggedin = function () { homecoming boolean($sessionstorage.isloggedin); }; $scope.login = function () { //if browser fills in username , password field angular's model not updated need //to manually pull them out of dom :(. see issue details: https://github.com/angular/angular.js/issues/1460 var username = $('#usernameinput').val(); var password = $('#passwordinput').val(); $scope.loginerrmsg = null; $http.jsonp("http://ldap-auth.otpp.me" + '/login?callback=json_callback&username=' + encodeuricomponent(username) + '&password=' + encodeuricomponent(password)) .success(function (data, isloggedin) { // app internal utilize only, security not major concern. // using sessionstorage store login status ok. $sessionstorage.displayname = data.displayname; $sessionstorage.isloggedin = true; }) .error(function () { $scope.loginerrmsg = "invalid username or password"; }); };

here test:

describe('controller: mainctrl', function () { // load controller's module beforeeach(module('uiappapp')); var mainctrl, $httpbackend, scope; // initialize controller , mock scope beforeeach(inject(function ($injector, $controller, $rootscope) { scope = $rootscope.$new(); mainctrl = $controller('mainctrl', { $scope: scope }); $httpbackend = $injector.get('$httpbackend'); })); it('should login', function () { var isloggedin = scope.isloggedin(); expect(isloggedin).tobe(false); var username = $('<input type="text" id="usernameinput"/>'); var password = $('<input type="text" id="passwordinput"/>'); $('body').html('<div>') .find('div') .append(username) .append(password); username.val('username'); password.val('password'); var response = $httpbackend.expectjsonp('http://ldap-auth.otpp.me/login?callback=json_callback&username=username&password=password'); response.respond({displayname: 'userx'}, {'a-token': 'xxx'}); scope.login(); expect(scope.isloggedin()).toequal(true); $('body').empty(); }); });

however test fails (expected false equal true.). seems didn't $httpbackend working. cannot figure out wrong. want mock $http.jsonp() response provide mocked-up json when unit testing , test user login.

thanks much if can help!

@hackedbychinese after folloing step, have:

it('should login', function () { var isloggedin = scope.isloggedin(); expect(isloggedin).tobe(false); var username = $('<input type="text" id="usernameinput"/>'); var password = $('<input type="text" id="passwordinput"/>'); $('body').html('<div>') .find('div') .append(username) .append(password); username.val('username'); password.val('password'); var response = $httpbackend.expectjsonp('http://ldap-auth.otpp.me/login?callback=json_callback&username=username&password=password'); response.respond({displayname: 'userx'}, {'a-token': 'xxx'}); scope.login(); $httpbackend.flush(); expect(scope.isloggedin()).toequal(true); $('body').empty(); });

but got next error message:

error: unexpected request: views/main.html no more request expected @ $httpbackend (c:/repo/docserver-ui/uiapp/app/bower_components/angular-mocks/angular-mocks.js:1177:9) @ sendreq (c:/repo/docserver-ui/uiapp/app/bower_components/angular/angular.js:7967:9) @ $get.serverrequest (c:/repo/docserver-ui/uiapp/app/bower_components/angular/angular.js:7708:16) @ deferred.promise.then.wrappedcallback (c:/repo/docserver-ui/uiapp/app/bower_components/angular/angular.js:11100:81) @ deferred.promise.then.wrappedcallback (c:/repo/docserver-ui/uiapp/app/bower_components/angular/angular.js:11100:81) @ c:/repo/docserver-ui/uiapp/app/bower_components/angular/angular.js:11186:26 @ scope.$get.scope.$eval (c:/repo/docserver-ui/uiapp/app/bower_components/angular/angular.js:12175:28) @ scope.$get.scope.$digest (c:/repo/docserver-ui/uiapp/app/bower_components/angular/angular.js:12004:31) @ function.$httpbackend.flush (c:/repo/docserver-ui/uiapp/app/bower_components/angular-mocks/angular-mocks.js:1435:16) @ null.<anonymous> (c:/repo/docserver-ui/uiapp/test/spec/controllers/main.js:43:22) process finished exit code 0

and here partial html:

<form class="navbar-form navbar-right" role="form" ng-show="!isloggedin()"> <p class="navbar-text" id="loginerrmsg">{{loginerrmsg}}</p> <div class="form-group"> <input type="text" placeholder="user name" id="usernameinput" class="form-control" ng-class="{'error-fields': loginerrmsg}"> </div> <div class="form-group"> <input type="password" placeholder="password" id="passwordinput" class="form-control" ng-class="{'error-fields': loginerrmsg}"> </div> <button type="submit" class="btn btn-success" ng-click="login()">sign in</button> </form>

after calling scope.login() , before expect(...), need phone call $httpbackend.flush() respond specified expectations.

this not specific jsonp, unit testing $http calls in general.

to summarize, here steps unit test code makes $http requests:

set expectations using $httpbackend. invoke code makes $http call(s). call $httpbackend.flush() create respond pending requests expectations set up. make test assertions.

see docs regarding flush.

javascript angularjs jasmine karma-runner karma-jasmine

No comments:

Post a Comment