Measuring the length of $scope in Angular controller unit testing

Currently, I am in the process of testing a controller that is linked to a service responsible for fetching data using $http.

storesController.js

(function () {
    var app = angular.module('storesController', ['storesService']);

    app.controller('StoresListController', function ($scope, StoresService) {

        $scope.getStores = function () {
            StoresService.getStores().then(function (data) {
                $scope.stores = data.data;
            });
        };
        $scope.getStores();

        $scope.deleteStore = function (id) {
            StoresService.deleteStore(id).then(function () {
                $scope.getStores();
            });

        };
    });
})()

storesService.js

(function () {
    var app = angular.module('storesService', []);

    app.factory('StoresService', ['$http','appConfig', function ($http,appConfig) {

            var webServiceUrl = appConfig.webServiceUrl;
            var stores = [];

            stores.getStores = function () {
               return $http.get(webServiceUrl + 'getStores');
            };            
            return stores;

        }]);

})();

Furthermore, I have included my test below:

describe("Store Controller", function () {
var StoresService, createController, scope;

beforeEach(function () {
    module('storesController');
    module(function ($provide) {
        $provide.value('StoresService', {
            getStores: function () {
                return {
                    then: function (callback) {
                        return callback([
                            {name: "testName", country: "testCountry"},
                            {name: "testName2", country: "testCountry2"},
                            {name: "testName3", country: "testCountry3"},
                        ]);
                    }
                };
            },
        });
        return null;
    });
});

beforeEach(function () {
    inject(function ($controller, $rootScope, _StoresService_) {
        scope = $rootScope.$new();
        StoresService = _StoresService_;
        createController = function () {
            return $controller("StoresListController", {
                $scope: scope,
            });
        };
    });
});

it("An assertion to ensure the store service retrieves the store list", function () {
    createController();
    expect(scope.stores.length).toBe(3);
});

});

Despite my efforts, I have encountered an error message stating:

TypeError: scope.stores is undefined 

This situation might require a different strategy involving $httpBackend. As I navigate through my initial steps with unit testing, I find myself seeking guidance and assistance. Any suggestions or help would be greatly appreciated!

Answer №1

It's possible that implementing the following code will make everything function as expected:

return callback({ data: [
                            {name: "testName", country: "testCountry"},
                            {name: "testName2", country: "testCountry2"},
                            {name: "testName3", country: "testCountry3"},
                        ]}); 

However, an alternative approach could be creating a simulated promise for better readability and reduced chances of errors. This technique might look something like this:

describe("Store Controller", function () {
    var StoresService, createController, scope, $q;

    beforeEach(function () {
        module('storesController');
        module(function ($provide) {
            $provide.value('StoresService', {
                getStores: function () {},
            });
            return null;
        });
    });

    beforeEach(function () {
        inject(function ($controller, $rootScope, _StoresService_, _$q_) {
            $q = _$q_;
            scope = $rootScope.$new();
            StoresService = _StoresService_;
            createController = function () {
                return $controller("StoresListController", {
                    $scope: scope,
                });
            };
        });
    });

    it("should call the store service to retrieve the store list", function () {
        var deferred = $q.defer();
        // Simulate fake promise.
        spyOn(StoresService, 'getStores').and.returnValue(deferred.promise);

        createController();
        // Fulfill fake promise with some data.
        deferred.resolve({ data: 'some data'});
        // Promise's callback won't execute without digest cycle:
        $rootScope.$digest();

        expect(scope.stores).toEqual('some data');
    });
    });

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

Switching the theme color from drab grey to vibrant blue

How can I change the default placeholder color in md-input-container from grey to Material Blue? I have followed the instructions in the documentation and created my own theme, but none of the code snippets seems to work. What am I doing wrong? mainApp. ...

Tips and Tricks for Managing an Extensive Array of AJAX Requests (Exceeding 1000)

My application is retrieving a User's Google Contacts from the Google Contacts API on the front end, resulting in a variable number of JSON objects, usually ranging between 1 to 2000. Upon receiving these objects, the app goes through each one, reform ...

Unable to use computeVertexNormals with a model loaded from JsonLoader

Why does the model always display in FlatShading even though I have used computeVertexNormals? The model is exported without normals for optimization purposes, loaded into 3JS using JsonLoader, and converted to BufferGeometry. The material is set to Smoot ...

Is it possible for me to adjust the size of the Facebook login button on my website?

I have implemented a Facebook login on my website using the following code: <fb:login-button scope="public_profile,email" onlogin="checkLoginState();"> </fb:login-button> Is it possible to replace this button with a standard button or adjust ...

What is the best way to substitute </br> and <br/> with in a text?

Is there a way to replace </br> and <br/> with \n functionally? There seems to be varied responses to this query. Errors are often made when writing the break tag. The solutions for both types of breaks mentioned above are detailed below ...

The Mongoose function effectively records accurate data, however when utilizing an async function to retrieve it, the outcome is

I am currently working on retrieving data from a database and passing it to a function. The main issue I'm facing is that even though the query results are visible when logged, they appear as undefined when trying to access them through the function. ...

Text box is not automatically filling up when selecting from dropdown menu

I am currently facing an issue with a dropdown box that offers three different selections. I want the Group ID associated with the selected group to automatically populate in the textbox below. How can I achieve this functionality? Whenever I make a selec ...

What is causing the error "Next is not a function" to occur when exporting a Middleware function to the module.exports object?

In my logger.js module, I have a middleware function that I import into app.js and utilize. // ------ File : logger.js ------ // function log(req, res, next) { console.log('Logging details ... '); next(); } module.exports = log; // ---- ...

Unable to assign a value to a variable in JavaScript

Today, I delved into the world of JavaScript and decided to test my skills by creating a page that changes images when clicking on a div. Everything worked perfectly until I wanted to add an input element to specify how many steps to jump each time the but ...

What methods can be used to validate this dependency?

Context I am currently experimenting with a basic cache module, but I'm facing difficulty in maintaining the API as is while also injecting dependencies. Implementation const myCache = () => { //this serves as a dependency. //I'd p ...

Building a dynamic form using React Material-UI Autocomplete and integrating it with react

I'm encountering an issue where the MUI Autocomplete is not displaying the selected fields even though the react-hook-form values have been updated. Here is the code snippet import { useForm, Controller, FormProvider } from "react-hook-form" ...

Transferring data to a view

I have a dilemma with handling user selections from a select option list and a jstree object in Django. My goal is to pass these choices to a Django view for processing and obtain a response. I've encountered an issue where the template fails to load, ...

Tips for Waiting for Binding in an Angular 1.5 Component (No Need for $scope.$watch)

Currently, I am in the process of developing an Angular 1.5 directive and have encountered a frustrating issue related to manipulating data that is not yet available. Below is a snippet of my code: app.component('formSelector', { bindings: { ...

The inline style fails to take effect on input elements that are generated dynamically

Consider: $( "#scanInDialogItems tr td:nth-child( 3 )").mouseenter( function() { var q = $( this ).html(); $( this ).html( "<input type='number' style='text-align:right width:50px' min='1' value='" + q + " ...

A mysterious property appearing in a Webpack plugin

Here is my webpack configuration file and package.json. When I execute the command webpack -w, I encounter the following error (shown below). I suspect it may be related to path strings. Any help would be greatly appreciated. webpack.config.js const HtmlW ...

Removing the navigation button from the hamburger menu

I am working on creating a semi-progressive top navigation bar. For the mobile viewport, the navigation bar will only display the logo and a hamburger button. When the button is clicked, various navigation menu options as well as the Log In and Sign Up bu ...

Tips for adjusting the ion-select popup height in Ionic

I've been attempting to customize the max-height property of a div that organizes elements in a popup using the interfaceOptions attribute in Ionic, but so far I haven't been successful. Here's what I have tried: cu ...

Obtaining Spotify API access token using JavaScript code on the front end

I've developed a web application that enables users to generate a list of songs by artists related to a selected artist. The goal is to link the user's Spotify account and create a playlist based on this generated song list, which requires obtain ...

How can I link a dropdown field's value to another input field in MeanJS?

How can I connect the selected value from a dropdown field to another input field using meanjs? Hello everyone, please take a look at this Plunker that I have created. My goal is to choose a 'school' in Plunker and then select the 'schoo ...

Encountered an error while trying to set up the route due to Router.use() needing

Within my app.js file, I have the following code: app.use('/', require('./routes')); //old routes app.use('/api', require('./api')); Additionally, I have an api folder containing an index.js file. This is what the ...