Exploring the process of setting up Jasmine tests for both services and controllers in Angular.js

I have been facing challenges in creating accurate tests for my Angular services and controllers, even though they are functioning correctly. I have searched extensively for a solution to this problem.

Below is an example of my controller:

angular.module('wideCmsAngularApp').controller('UserListCtrl', [
  '$scope',
  'userService',
  '$routeParams',
  function ($scope, userService, $routeParams) {

    // Retrieve quantity and offset from the URL format: /user/list/10/0
    var quantity = typeof $routeParams.quantity !== 'undefined' ? $routeParams.quantity : 10;
    var offset   = typeof $routeParams.offset !== 'undefined' ? $routeParams.offset : 0;

    $scope.users = userService.query({
      'param1' : quantity,
      'param2' : offset
    });

  }
]);

This controller relies on the following service:

angular.module('wideCmsAngularApp').factory('userService', [
  '$resource',
  function ($resource) {

    return $resource('http://localhost:1337/api/v1/user/:param1/:param2', {}, {
      'get'    : {method : 'GET'},
      'save'   : {method : 'POST'},
      'query'  : {method : 'GET', isArray:true},
      'remove' : {method : 'DELETE'},
      'delete' : {method : 'DELETE'}
    });
  }
]);

Check out the test scenario created for the controller:

describe('UserListCtrl', function() {

  beforeEach(module('wideCmsAngularApp'));

  var $controller;
  var $rootScope;
  var userService;

  beforeEach(inject(function(_$rootScope_, _$controller_, _userService_){
    $controller = _$controller_;
    $rootScope  = _$rootScope_;
    userService = _userService_;
  }));

  describe('when requesting a list of users', function() {
    it('should contain 4 users', function() {

      var $scope = [];
      var controller = $controller('UserListCtrl', {
        '$scope': $scope,
        'userService': userService,
        '$routeParams': {
          'quantity' : 10,
          'offset'   : 0
        }
      });

      expect($scope.users.length).toBe(4);
    });
  });
});

The outcome of the test (expecting an array with 4 users, but remains empty):

PhantomJS 1.9.8 (Mac OS X) UserListCtrl when asking for a list of users should return 4 users FAILED
    Expected 0 to be 4.
        at /somewhere/test/spec/controllers/user/list.js:31

Have you identified any missing elements here?

--UPDATE--

I managed to resolve the issue using a workaround solution, although it is not ideal as I preferred making actual API requests. Is there a way to achieve that or do I need to settle for mock responses?

New test configuration for UserListCtrl, utilizing $httpBackend:

var $httpBackend;
var $controller;
var $rootScope;
var userService;

describe('UserListCtrl', function() {

  beforeEach(module('wideCmsAngularApp'));

  beforeEach(inject(function ($injector) {

    var uri = 'http://localhost:1337/api/v1/user/10/0';
    var users = [
      {
        "id": "555daff2862a513508a52ecd",
        "name": "Gru"
      },
      {
        "id": "555daff3862a513508a52ece",
        "name": "Kevin"
      },
      {
        "id": "555daff3862a513508a52ece",
        "name": "Ed"
      },
      {
        "id": "555daff3862a513508a52ece",
        "name": "Tim"
      }
    ];

    httpBackend = $injector.get('$httpBackend');
    httpBackend.whenGET(uri).respond(users)

    $controller = $injector.get('$controller');
    $rootScope  = $injector.get('$rootScope');
    userService = $injector.get('userService');
  }));

  describe('when requesting a list of users', function() {
    it('should contain 4 users', function() {

      var $scope = $rootScope.$new();
      var controller = $controller('UserListCtrl', {
        '$scope': $scope,
        'userService': userService,
        '$routeParams': {
          'quantity' : 10,
          'offset'   : 0
        }
      });

      httpBackend.flush();

      expect($scope.users.length).toBe(4);
    });
  });
});

Answer №1

For comprehensive testing, consider utilizing Protractor for end-to-end testing. This will allow you to receive authentic server responses instead of relying on httpbackend.

Answer №2

    angular.module('wideCmsAngularApp').factory('userService', [
      '$resource',
      function ($resource) {

        return $resource('http://localhost:1337/api/v1/user/:param1/:param2', {}, {
          'get'    : {method : 'GET'},
          'save'   : {method : 'POST'},
          'query'  : {method : 'GET', isArray:true},
          'remove' : {method : 'DELETE'},
          'delete' : {method : 'DELETE'}
        });
      }
    ]);

Reviewing line 4,

$resource('http://localhost:1337/api/v1/:param1/:param2', {}, {
, it is evident that three parameters are being passed - the URL, paramDefaults, and actions. Notably, no paramDefaults are being specified as indicated by the empty curly braces {} after :param2',. However, the controller has set paramDefaults;

$scope.users = userService.query({
      'param1' : quantity,
      'param2' : offset
    });

Hence, these values need to be incorporated into $resource.

$resource Documentation

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

What is the best way to display text from a file on a different html page using jQuery's json2html?

Here is the json data: var data = [ { "name": "wiredep", "version": "4.0.0", "link": "https://github.com/taptapship/wiredep", "lice ...

Tips for exporting a React Component without using ownProps in a redux setup with TypeScript

I'm currently working on a project using typescript with react-redux. In one of my components, I am not receiving any "OwnProp" from the parent component but instead, I need to access a prop from the redux state. The Parent Component is throwing an er ...

Issue with dynamic HTML preventing Bootstrap tooltip functionality

There's an HTML page where a section is dynamically generated through HTML injection from a typescript angularjs controller using $sce and ng-bind-html. The issue is that the custom bootstrap tooltip style doesn't seem to be applied, and only t ...

Assign the value/text of a div element by using JavaScript/jQuery within a PHP loop

I'm struggling to figure out how to set the value/text of a div using javascript/jquery inside a loop. Can anyone offer some guidance on this issue? Goals: Extract data from a database. Use javascript/jquery to assign the extracted data to an eleme ...

Forced line break at particular point in text

I would love to implement a line break right before the "+" character, either using css styling or through a different method. Is this task achievable? #myDiv{ width: 80% } #myP{ c ...

Having trouble with adding a class on scroll?

My challenge is to extract the header from this website, by adding an additional class when the user scrolls at a position greater than 0. I thought it would be easy, but Java always presents problems for me. Here’s the code I came up with: <!DOCTY ...

What is the best way to merge angularjs modules?

In my angularjs application using the codeigniter PHP framework, I have implemented 3 modules - cars.js for car details, cellphones.js for cellphone details, and home.js for home details. Each module caters to a different client's needs. I am trying ...

Can a faulty image be cached?

Is there a way to ensure that the browser caches invalid or broken images so that when they are re-fetched, the loading time is immediate? I am particularly interested in two scenarios: 1) The first scenario involves trying to load an image from a URL co ...

Using a bound data variable in a filter within an ng-repeat loop (Angular JS)

<!-- Left Navbar --> <div class="container-fluid" style="margin-top: 50px"> <div class="row"> <div class="col-sm-3 col-md-2 sidebar"> <ul ng-repeat="type in types" class="nav nav-sidebar"> <li>{{ ...

I am encountering an issue with Angular where the following error message is displayed: "src/app/app.component.html:18:20 - error TS2339: Property 'DepScreen' does not exist on type 'AppComponent'"

This code snippet is from my app.component.html file: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0" ...

Sending a parameter to the window.onload callback function

Is there a way to pass parameters from ModelAndView to a window.onload function in JavaScript within an HTML file? Here is an example of how it can be done: @RequestMapping(value = "/admin/printtext") public ModelAndView printtext() { ModelAndView mo ...

Check to see if my Node.js server is running in development or production mode

Lately, I've been facing a tedious task every time I deploy a node.js server to my production server. It involves changing all the IP addresses, DNS settings, usernames, and passwords for my various connections to databases and external APIs. This en ...

Using multiple ng-controller directives with the "controller as x" syntax on a single element

What is the reason that Angular does not allow two ng-controller directives on a single element and What are some potential solutions for this issue - such as using custom directives or nesting HTML elements with a single ng-controller directive, among oth ...

Issue with Github actions: Failure in mark-compacts process due to ineffective operation near heap limit causing allocation failure - running out of memory in

Whenever I try to build my library files, I keep encountering an out of memory error. In my local setup, I was able to resolve this problem by executing the command export NODE_OPTIONS="--max-old-space-size=8192". Unfortunately, no matter how mu ...

Tips for expanding a script that relocates a logo into a navigation consisting of several unordered lists

I recently implemented a jQuery script to center a logo within my main navigation bar only when the screen width is above 980 pixels. It was working perfectly fine with a single unordered list, but as soon as I added more unordered lists within the nav, it ...

The issue arising from Firefox's handling of try/catch blocks in window.onerror is not adequately addressed

It appears that Firefox handles errors differently when they occur in the window.onerror event handler compared to other browsers. While IE, Chrome, and Safari behave as expected, Firefox seems to treat any error in this context as a critical exception, ev ...

Ways to enhance filtering capabilities in AngularJS?

Currently, I am using the following ng-model: <input ng-model="query" type="text" iplaceholder="Add New Filter"></input> This is how I am presenting my data: <ul> <li role="menuitem" ng-repeat="item in availableFilters | filter:qu ...

Managing and retrieving data in bulk from an indexed database as JSON format

I am currently developing an application that utilizes IndexexDB for local data storage. I am looking for a way to extract and insert large amounts of data from an indexed DB in JSON format. Below is the code snippet illustrating what I have accomplished s ...

Changing the position of the icon in the bootstrap validator

I'm currently attempting to validate form fields in a web project. The goal is to achieve a specific result, similar to the image below: https://i.stack.imgur.com/EVeJf.png While I have made progress with a simple solution that almost meets the requi ...

Adding an image to a React component in your project

I am currently working on an app that utilizes React and Typescript. To retrieve data, I am integrating a free API. My goal is to incorporate a default image for objects that lack images. Here is the project structure: https://i.stack.imgur.com/xfIYD.pn ...