Experimenting with Angular Jasmine to validate a factory function

As a beginner in Angular, I am diving into unit testing for the first time. Let's take a look at the module I'm working with:

var app = angular.
module('webportal',
[
    'vr.directives.slider',
    'angular-flexslider',
    'LocalStorageModule',
    'multi-select',
    'djds4rce.angular-socialshare'
]).run(function ($FB) {//facebook share...should we move this somewhere else?
    $FB.init('xxxxx')
});

Additionally, there are two factories to consider:

angular.module('webportal').factory('uri', function () {

    var uri = {};

    uri.base = '';

    uri.setBase = function (base) {
        uri.base = base;
    };


    uri.getBase = function () {
        return uri.base;
    }

    return uri;
});

app.factory('portal', ['uri', function (uri) {
    var portal = {};
    portal.getLink = function (id) {
        return uri.getBase() + langHalf + '/property/' + id;
    };
    return portal;
}])

My goal is to test the functions within the uri and portal factory.

Here is my attempt:

 

describe('Unit: Factory Test', function () {

    var uri;

    beforeEach(function () {
        angular.mock.module('vr.directives.slider', []);
        angular.mock.module('angular-flexslider', []);
        angular.mock.module('LocalStorageModule', []);
        angular.mock.module('multi-select', []);
        angular.mock.module('djds4rce.angular-socialshare', []);

        module('webportal', [
            'vr.directives.slider',
            'angular-flexslider',
            'LocalStorageModule',
            'multi-select',
            'djds4rce.angular-socialshare'
        ]);

        beforeEach(module('uri'));


    });


    it("baseSettingTest", function () {
        var uri = new uri();
        //var uri = new uri;
        var baseSettingTest = 'testing base';
        uri.setBase(baseSettingTest);

        expect(uri.getBase()).toEqual(baseSettingTest);

    })

})

However, upon running the test, I encountered the following error:

FAILED Unit: Factory Test baseSettingTest
TypeError: undefined is not a function
    at Object.<anonymous> (http://localhost:9876/base/tests/portaltestjs/portal.test.js:50:19)
    at attemptSync (http://localhost:9876/base/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1759:24)
    at QueueRunner.run (http://localhost:9876/base/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1747:9)
    at QueueRunner.execute (http://localhost:9876/base/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1733:10)
    ...

It seems I am not initializing the uri factory correctly.

  1. How should I properly initialize the uri factory and test a function?
  2. How can I initialize the portal factory and test a function?

Answer №1

To utilize the service and access its methods, you must first inject the service. Below is an example of how I accomplished this in my project called ng-boilerplate:

  beforeEach(module('ng-boilerplate'));

  var NameService;
  beforeEach(inject(function (_NameService_) {
    NameService = _NameService_;
  }));

  describe('#formatName()', function() {
    it('should convert a given string to title case', function() {
      expect(NameService.formatName('IAN')).to.equal('Ian');
  // ...etc...

Answer №2

Ensure to include a reference to your 'uri' template before proceeding.

describe('Unit: Factory Test', function () {

    var uri;

    beforeEach(function () {
        angular.mock.module('vr.directives.slider', []);
        angular.mock.module('angular-flexslider', []);
        angular.mock.module('LocalStorageModule', []);
        angular.mock.module('multi-select', []);
        angular.mock.module('djds4rce.angular-socialshare', []);

        module('webportal', [
            'vr.directives.slider',
            'angular-flexslider',
            'LocalStorageModule',
            'multi-select',
            'djds4rce.angular-socialshare'
        ]);

        //beforeEach(module('uri')); please comment out this line
        beforeEach(module('webportal')) //you should load module instead of load your factory

    });

    // Use below block code to inject your factory into uri variable
    beforeEach(inject(function (_$injector_) {
        uri = _$injector_.get('uri');   //Inject uri factory into uri variable
    }));

    // For now your uri factory available for testing

    it("baseSettingTest", function () {
        spyOn(uri, 'setBase'); //spy on you setBase function

        var baseSettingTest = 'testing base';
        uri.setBase(baseSettingTest);       

        expect(uri.getBase).toHaveBeenCalled(); //Make sure getBase function was called
    })
})

I made some modifications to your code, hoping it can assist you.

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

"Encountering an issue with ASP.NET MVC and Angular when making an AJAX call with multiple parameters, the HttpPostedFileBase

When sending an object and a file from my Angular service, the following code snippet is executed: $scope.addProject = function () { { var project = {}; project["Id"] = $scope.Id; project["ProjectCode"] = $scop ...

Issue with Vue.js: Child component emitting event but parent component method not triggering

When a child component makes an input change, it emits an event with some data: Vue.component('gum-option', { inheritAttrs: false, props: ['label'], template: ` <label class="gum-option"> ...

Using AngularJS's $watchCollection in combination with ng-repeat

Encountering difficulties receiving notifications for changes in a list when utilizing an input field within ng-repeat directly. However, I am able to modify values and receive notifications from $watchCollection. To illustrate: <!DOCTYPE html> < ...

Any tips on incorporating authentication details into URLs with AngularJS?

I am seeking guidance on how to include authentication details, like username and password, in the URL for accessing a REST API through AngularJS. Can someone help me with this? ...

Jquery display function experiencing unresponsiveness

Currently, I am trying to implement some show/hide functionality in my JavaScript file: $(document).ready(function() { $('#me').hide(); $('#send').click(function() { $('#me').show("slow"); }); }); Strange ...

Combining objects in JavaScript

I am currently working on converting the object received from the server into a format compatible with the backend system. I have a received object that looks like this { 'User.permissions.user.view.dashboard': true, 'Admin.permissio ...

What is the best way to navigate through the underlying MatDialog while the MatSelect is active?

When attempting to customize the scroll behavior of a MatSelect in a regular page, I discovered that using the MAT_SELECT_SCROLL_STRATEGY injection token with the NoopScrollStrategy allows for scrolling the underlying page while keeping the MatSelect stati ...

My data is not appearing with ng-repeat or ng-bind

One issue I am encountering is that my ng-repeat / ng-bind is not displaying the data within $scope.articles, even though I am getting the expected data in the console. To help identify the problem more easily, I have created a code snippet below: var A ...

What is the best way to integrate a Vue component into a Knockout application?

My webpage is filled with knockout code, but I'm hoping to integrate a Vue.js component for a specific section. I attempted using controlsDescendantBindings on a surrounding tag for the Vue component, and it seems to be partially functional (I tried ...

Send multiple values as arguments to a jQuery function

Beginner question ahead: I'm using the jquery function loadNewPicture() to upload pictures and the progress() function to track the percentage of the upload. Everything is functioning correctly. My query relates to the variables that can be passed t ...

beforeunload event confirmation prompt

I am currently working with Laravel and Vue.js to create a multi-step wizard. Within this wizard, I have implemented the onbeforeunload event to prevent any unwanted actions by displaying a confirmation message. However, I am encountering an issue where th ...

Display the files contained within a folder on the right side of a container by utilizing vue.js

I am currently working on an application that involves a list of folders, each containing various files. The goal is to display these files when a specific folder is chosen. On the left side, users will see a list of folders and on the right side, the resp ...

Exploring data elements in a Javascript array

Is there a way to use Javascript or jQuery to address the individual employee number, tasks, and sites in the following JSON array? $.each(mySchedule, function(i, obj) { console.log(obj.employees); }); var mySchedule = { "schedule": { "empl ...

Installing a package from a private repository using a different package name with npm

I'm looking to incorporate a module from a private GitHub repository into my project. To achieve this, I will execute the command npm install git+https://[API-KEY]:<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="0b737c6e607 ...

What is the method for attaching a keypress event to an HTML document?

Looking to add an interactive touch to my website by creating a "press any key" page. When a key is pressed, I want it to kick off animations that bring the page to life - like sliding elements in from different directions. Open to using jQuery or plain ...

The form validation feature is not functioning as expected when integrating mui-places-autocomplete with MUI React

I'm currently working on implementing an autocomplete feature using Google Places API in my project with Material UI React, Redux-Form, Revalidate, and MUI-Places-Autocomplete. Although I've successfully integrated the place lookup functionality, ...

Error message: "The function platform_browser_dynamic_1.bootstrap does not exist in Angular 2."

I had everything set up and running smoothly until suddenly I started receiving this error out of nowhere: TypeError: platform_browser_dynamic_1.bootstrap is not a function Here's the component I've been working on: import { Component, Input, ...

Warning: Using synchronous XMLHttpRequest on the main thread is no longer recommended as it can negatively impact the user's experience

I encountered an issue with my project while attempting an Ajax request [Warning] Using synchronous XMLHttpRequest on the main thread is now considered deprecated due to its negative impact on user experience. function retrieveReviews() { var reviewsD ...

Display the invoice bill using text in a Vue component

Hello, I am looking to print an invoice that resembles the one shown in this picture https://i.sstatic.net/6mzwe.jpg However, when I try to print it, I get a different output with some additional elements https://i.sstatic.net/uaKZC.jpg I am using vue. ...

Node.js: Steps for receiving an ArrayBuffer in a $http request

I made a request using $http.post from Angular.js to Node.js, expecting to receive an ArrayBuffer. Here is the code snippet: $http.post('/api/scholarships/load/uploaded-files', Global.user, {responseType:'arraybuffer'}).success(functi ...