Struggling to pass jasmine test when calling injected service

I've been grappling with unit testing in Angular and have hit a few obstacles along the way. While trying to set up a plnkr for my question regarding a failing Jasmine test that's making an $httpbackend call, I encountered a different error. It would be incredibly helpful if someone could assist me in resolving this plunkr conundrum, as it may also lead to a solution for the original issue. You can find the question here: Jasmine test fails making $httpbackend call and the plunkr here: http://plnkr.co/edit/lJTx0ldR9nEnlYbU5pJd

(function(){'use strict';
  var RestService = function($http, $rootScope){
    var _postData = function(url, params, data, successFunction,  errorMsg, errorFunction, config) {

            if(config && config.hasOwnProperty('showLoader')){
                $rootScope.showLoader = config.showLoader;
            }

            $http({
                method: 'POST',
                url: url,
                params: params,
                data: data,
                cache: false
            })
                .success(function(data, status, headers, config) {
                    $rootScope.showLoader = false;
                    if (successFunction === undefined) {
                        _defaultSuccessFunction(data, status, headers, config);
                    }
                    else {
                        successFunction(data, status, headers, config);
                    }
                })
                .error(function (data, status, headers, config) {
                    $rootScope.showLoader = false;
                    if(status === 401){
                        _processError(data, status, headers, config, errorMsg, errorFunction);
                    }
                });
        };

        return {
            postData: _postData
        };
  };
  angular.module('ram-utilities.ui.rest.service', []).factory('RestService', ['$http', '$rootScope', RestService]);
})();

(function(){ 'use strict';
    var LoginController = function($scope, RestService){
        var _user = undefined;
        var _message = 'hello';

        var _login = function(user){
            var _success = function(response){
                _message = response.success;
                _user = response.user;
            };

            var _error = function(response){
                _message = response.success;
            };

            RestService.postData('/api/login',  null, {username: user.username, password: user.password}, _success, 'Invalid login, please try again', _error, {showLoader: true});
        };

        $scope.model = {
            login: _login,
            user: _user,
            message: _message
        };
    };

    angular.module('danny',['ram-utilities.ui.rest.service']).controller('LoginController',['$scope', 'RestService',LoginController]);
})();

describe('LoginController', function(){
    var scope, $httpBackend, controller, restService;

    beforeEach(function(){
        module('danny');
    });

    beforeEach(inject(function(_$controller_, _$rootScope_, _$httpBackend_, _RestService_){
        $httpBackend = _$httpBackend_;
        restService = _RestService_;
        scope = _$rootScope_.$new();
        controller = _$controller_('LoginController', {
            $scope: scope,
            RestService: restService
        });
    }));

    afterEach(function() {
        $httpBackend.verifyNoOutstandingExpectation();
        $httpBackend.verifyNoOutstandingRequest();
    });

    describe('successfully logging in', function(){

       it('should redirect to /blog when authenticated', function(){

           var user = {"username":"example@example.com", "password":"test"};
            expect(user.username).toEqual('example@example.com');

          $httpBackend.expectPOST('/api/login', user).response(200, {});

          scope.model.login(user);
          $httpBackend.flush();

          expect(scope.model.user).not.toBe(undefined);
       });
    });
});

(function() {
  var jasmineEnv = jasmine.getEnv();
  jasmineEnv.updateInterval = 250;

  /**
   Create the `HTMLReporter`, which Jasmine calls to provide results of each spec and each suite. The Reporter is responsible for presenting results to the user.
   */
  var htmlReporter = new jasmine.HtmlReporter();
  jasmineEnv.addReporter(htmlReporter);

  /**
   Delegate filtering of specs to the reporter. Allows for clicking on single suites or specs in the results to only run a subset of the suite.
   */
  jasmineEnv.specFilter = function(spec) {
    return htmlReporter.specFilter(spec);
  };

  /**
   Run all of the tests when the page finishes loading - and make sure to run any previous `onload` handler

   ### Test Results

   Scroll down to see the results of all of these specs.
   */
  var currentWindowOnload = window.onload;
  window.onload = function() {
    if (currentWindowOnload) {
      currentWindowOnload();
    }

    //document.querySelector('.version').innerHTML = jasmineEnv.versionString();
    execJasmine();
  };

  function execJasmine() {
    jasmineEnv.execute();
  }
})();

Thank you for your assistance!

Answer №1

Here are a couple of important points to consider:

  1. When using $httpBackend.expectPOST, be sure to use respond instead of response

  2. Rename the hidden data argument in $http.success handler to postData. Also, make sure to pass the expected object to the success callback.

var _postData = function(url, params, data, successFunction /* ... */) {
    //...

    $http( {
        method: 'POST',
        url: url,
        params: params,
        data: data,
        cache: false
    } )
        .success( function ( postData, status, headers, config ) {
            // ...
            successFunction({
                success: true,
                user: data
            }, status, headers, config);
        } );

    //...
}
  1. Be cautious when dealing with objects returned by LoginController. Make sure to only change them through explicit referencing such as

    $scope.model.user = response.user;
    . Simply calling _user = response.user won't affect $scope.model.user unless wrapped in a closure.

  2. Check out this Working Plunk example

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Why isn't the ng-repeat object being updated?

This particular function is responsible for loading listings from the server. Currently, even after receiving a null response when applying filters, the previous results are still displayed without clearing them. $scope.browseListing = function (strURL) ...

Encountering an unknown value within the inner array of a JSON response when using Angular

I received the following JSON data from an API: [ { "CinemaId": "Hfsdfsdfs", "FilmCode": "HIWdfsdfsfsf47", "FilmTitle": "BAfsdfAAR", "CinemaName": "CsfsnfsfsAhmedabad", "CinemaCity": "Ahmedabad", "CinemaLicenseName": "BIGdfsfsAh ...

Find the position of an HTML5 canvas element within a webpage

I am currently facing an issue with a canvas within another canvas. <canvas id ='canvas2' height="718" width="1316"></canvas> The CSS for this canvas is as follows: #canvas2{ position:absolute; width :95%; height:90%; top:5%; lef ...

Utilize the precise Kendo chart library files rather than relying on the kendo.all.min.js file

My application currently uses the Kendo chart, and for this purpose, it utilizes the "kendo.all.min.js" file which is quite large at 2.5 MB. To optimize the speed performance of the application, I decided to only include specific Kendo chart libraries. In ...

Error: Cannot read property 'X' of undefined in JavaScript when using Django framework

Using p5.js, I am creating drawings with data from a JSON provided by my Django backend. The draw function is defined at the base level of my HTML document within the script element: function draw(json) { if (json["leaf_text"]) { stroke(100) el ...

Retrieve the data stored in a selection of checkbox fields on a form

I have a table of checkboxes: <div> <h1 class="text-center">Select activities</h1> <div class="row"> <div class="col"></div> <div class="col-md-8 col-lg-8"> <h3>Link activ ...

What methods can I employ to utilize PHP or JS/HTML for posting to two separate URLs simultaneously?

Is it possible to submit a form from one button to two different locations? I am looking for a solution to achieve this. After clicking the submit button on a form, the form tag looks like this: <FORM ACTION="http:site.com/servlets/RequestServlet" met ...

Issue encountered during Heroku deployment: Failed to build React app. When attempting to push changes to Heroku, an unexpected end of input error was received instead of the expected result. This error occurred on an unidentified file at

Encountering a parsing error while attempting to deploy a React app on Heroku using git push heroku master. The app built successfully yesterday, but since then some media queries were added by another contributor to various .scss files. The primary error ...

ReactJS Tutorial: Simple Guide to Updating Array State Data

const [rowData, setRowData] = useState([]); const old = {id: 'stud1', name: 'jake', room: '2'}; const newData = {name: 'jake', room: '3A'}; useEffect(() => { let ignore = false; ...

What is the best way to determine if a checkbox has been selected in ExtJS?

I have a panel with a checkbox inside it. I am trying to figure out how to check if the checkbox is selected or not using an external function. Can someone please assist me with this? this.currentManagerPanel = new Ext.Panel({ border: false, wid ...

gdal.vectorTranslate causing output files to be void

Attempting to use gdal-async in nodejs for converting vector files from geojson to dxf. const dsGeoJSON2 = gdal.open('./upload2/objects.geojson'); const out2 = gdal.vectorTranslate('./upload2/objects.dxf', dsGeoJSON2, ['-f', ...

Display the input text line by line

How can I achieve the desired output for this input parameter? displayText("you and me"); expected output: ["you and me", "you and", "and me", "you", "and", "me"] I have attempted ...

Utilizing jQuery's extend method for object inheritance in a function

I've been experimenting with using jquery extend to simulate inheritance, but it seems that it only works with objects based on my testing. My goal is to achieve the following: var baseDefinition = function() { var self = this; self.calc1 = ...

Is there a specific jest matcher available for comparing Array<Objects>?

I'm currently testing the equality of two arrays of objects and have found that the toEqual matcher in Jest only works for arrays of strings. Is there another matcher available in Jest that can handle this condition? Please refrain from marking this a ...

"Reacting to click events, all buttons have been successfully updated in ReactJS

When a button is clicked, all buttons are updated simultaneously. However, I am looking to only change the state of the specific button that is clicked. Please refer to the image links and code provided below. import React from 'react'; import & ...

JavaScript: Modifying an Array of Matrices

Could anyone assist me with updating a matrix array? I have an initial matrix with preset values and need to update specific coordinates within it. Here is the base matrix: var myMatrix = [ ['-','-','-','-',&ap ...

What is the best way to navigate to a component that has been imported in Vue.js?

I have knowledge of Vue's scrollBehavior function, but I am struggling to integrate it with my existing code. On my Index page, I have sections composed of imported Vue components like this: <template> <div class="Container"> <Ab ...

When choosing the child option, it starts acting abnormally if the parent option is already selected in Angular

I am encountering an issue while trying to select the parent and its children in the select option. The concept is to have one select option for the parent and another for the child. I have parent objects and nested objects as children, which are subCatego ...

Ways to address Path Traversal vulnerability in the following code

const downloadFile = blobstoreRouter.get('/blobstore/download/:filename', (req, res) => { var localFile = path.join(__dirname, '..', escape(req.params.filename)); var file = require('fs').createWriteStream(localFile); try { ...

Why does the for loop function correctly with console.log but not with innerHTML?

Hello! I'm completely new to JavaScript, so please excuse any oversight... Below is the code that runs when a button on the page is clicked: function getNumbers() { var firstValue = document.getElementById("time_one").value; var ...