Testing an AngularJS Directive's Controller with Karma, Chai, and Mocha

Struggling to access my directive's scope for a unit test. Running into compile errors when trying to execute the unit test.

The application compiles (using gulp) and runs smoothly, and I am able to successfully unit test non-directives. However, testing directives has been challenging as I am experimenting with various solutions from other sources and making educated guesses.

Main page's HTML and JS

<div company-modal="companyOptions" show-close="false"></div>

.

(function() {
    'use strict';

    angular
        .module('app')
        .controller('companyModalCtrl', ['$scope', selectionPage]);

        function selectionPage($scope) {
            $scope.companyOptions = {};
        }
})();

This is just the initial part of my directive (as it's quite extensive so including only the crucial first section).

(function() {
  'use strict';

  angular
    .module('app')
    .directive('companyModal',
      companyModal
    );

  function companyModal() {
    return {
      restrict: 'A',
      replace: false,
      transclude: true,
      templateUrl: '/src/login/company.html',
      scope: {
        options: '=companyModal',
        showClose: '='
      },
      bindToController: true,
      controller: companySelection,
      controllerAs: 'csmvm'
    };
  }

  companySelection.$inject = ['$state'];

  function companySelection($state) {
    var csmvm = this;
    var url;
    csmvm.emailList = [];

Here is my Unit Test attempt

'use strict';

describe('Company', function () {

  var scope;
  var controller;
  var elem;

  beforeEach(module('app'));
  beforeEach(inject(function ($controller, $rootScope, $compile) {
    scope = $rootScope.$new();

    elem = angular.element('<div company-modal="companyOptions" show-close="false"></div>');
    $compile(elem)($rootScope);
    
    controller = $controller(elem.controller('companyModal as csmvm'), {
      $scope: scope
    });

    scope.csmvm.emailList.email = "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="9cdef3fedcfbf1fdf5f0b2fff3f1">[email protected]</a>";

  }));

  describe('Invite', function () {
    it('should be an array for emailList', function () {
      expect(scope.csmvm.emailList).to.be.an('array');
    });

  });

});

The issue I am encountering (apologies for the lack of detail) is that I consistently receive runtime errors during the test. For example:

Failed Tests:
   Company
     "before each" hook: workFn
       18) the object { "message": "'undefined' is not an object (evaluating    '(isArray(Type) : Type).prototype)".

Once again, my app compiles (gulp) without any issues and functions well, and I can successfully unit test non-directive components.

Answer №1

Ensure that you are testing the isolated scope of your directive.

Currently, the variable scope is referencing the scope where the directive was compiled.

Since your directive creates a new isolate scope, make sure to run expectations towards it.

There are two methods to accomplish this:

function isolateScope (el) {
  return el.isolateScope();
}

/** or **/

var el, scope, isolateScope; 

beforeEach(inject(function ($compile, $rootScope) {
  scope = $rootScope.$new();
  el = $compile('<directive></directive>')(scope);
  scope.$digest();
  isolateScope = el.isolateScope();
});

Based on the above, I suggest removing the controller from your directive spec suite and testing it separately. This approach leads to cleaner and more modular unit tests. It's beneficial to break them up for better organization.

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

variables that have been declared as jquery elements

What are the recommended practices for declaring jQuery DOM elements as variables? Is there any distinction between var div = $('div'); and var $div = $('div'); other than improved readability? Thank you ...

"Mastering the art of route handling with Node.js and

I am seeking some assistance with routing in my Node/Express application. Initially, I successfully create a new business from the Business model. After creating the business, I intend to have a separate route that adds the current FX rates offered by that ...

What is the correct way to add a period to the end of a formatted text?

Hello, this marks the beginning of my inquiry. I apologize if it comes across as trivial but I have come across this piece of code: function format(input){ var num = input.value.replace(/\./g,''); if(!isNaN(num)){ num = num.toString ...

Tips for optimizing the use of JS promises?

I'm encountering issues with implementing promises in JavaScript. There are 3 asynchronous functions that rely on each other: The functions are named func1, func2, and func3 respectively. func1 produces a single result that func2 requires. func2 a ...

Storing large data tables in C#: Tips for efficient caching

Currently, I am facing the challenge of executing a lengthy PL/SQL query and storing the result set in order to serve UI requests. Additionally, I need to refresh this data automatically or manually after some time. The complexity arises from handling mult ...

Tips for organizing a JSON object based on an integer column such as "3", "2", "5"

I am facing a challenge with sorting a JSON object that has a column containing numbers. The issue arises because the column is of string type. How can I sort string numbers in numerical order? var myArray = [{ name: 'David', total: "6" }, ...

What is the best way to attach 'this' to an object using an arrow function?

Consider having an object named profile which consists of properties name and a method called getName (implemented as an arrow function). profile = { name: 'abcd', getName: () => { console.log(this.name); } } I am interes ...

What is the process for adding an image to a designated directory using multer?

As a student working on a project to develop a simple website, I am faced with the challenge of enabling users to create listings and upload pictures akin to platforms like eBay. Additionally, I aim to incorporate user profile creation where images can be ...

Ways to identify when text wraps to the next line

I'm working on a navigation menu (.navigation) that I want to hide instead of wrapping onto the next line when the screen width is small. I've been trying to figure out how to use javascript/jQuery to detect when wrapping occurs and hide the navi ...

What is the method for showing all properties of a JavaScript array/object in the Chrome browser?

When it comes to JavaScript, there is a surprisingly confusing distinction between arrays and objects as well as array-like objects: var a = []; // empty array, right? a.foo = 'bar'; // a is also an object The issue arises when inspecting var ...

The issue of VueRouter malfunctioning in history mode within Wordpress

I have integrated Vue into my Wordpress theme, but I am facing an issue with the router when setting mode: 'history'. The site goes blank and even after trying to configure the .htaccess file, nothing seems to work. My project is located in the V ...

Ways to showcase logs on the user interface

After configuring a set of operations in the UI and initiating the operation, a Python script is called in the backend. It is necessary to display the logs generated by the Python script on the UI. I managed to implement this in a similar way as described ...

Utilizing $resource within a promise sequence to correct the deferred anti-pattern

One challenge I encountered was that when making multiple nearly simultaneous calls to a service method that retrieves a list of project types using $resource, each call generated a new request instead of utilizing the same response/promise/data. After doi ...

What is the best way to eliminate an element from a state using the useState hook?

I need help with generating a list of values from checkboxes. const [checkedState, setCheckedState] = useState({}); const handleOnChange = (e) => { if(e.target.checked === true){ setCheckedState({ ...checkedState, [e.target.name]: e.target.checke ...

When populating data, two ID fields (_id and id) are generated as duplicates

Upon retrieving information from my database, I have noticed the presence of an additional id field alongside the standard _id field. These two fields consistently contain identical values. However, it seems that the id field appears only during population ...

Fetching the Three.js mesh from the loader outside the designated area

Currently, I am immersed in a project that involves Three.js. The challenge I am facing is trying to access the mesh (gltf.scene) in the GLTF load from an external source. However, whenever I attempt to console.log outside of the loader, it shows up as und ...

Three.js Ellipse Curve Rotation

Purpose My goal is to create an EllipseCurve () where a camera will move. The Approach I Took to Achieve the Goal Below is the code snippet for creating the ellipse: var curve = new THREE.EllipseCurve( 0, 0, 1, 1, 0, 2 * Math.PI, false, ...

Having trouble with UseSelector in React Redux?

I am currently working on a exercise to better understand the react-redux process, but I seem to have hit a roadblock. Any assistance would be greatly appreciated. One interesting observation is that when I subscribe and log the store into the console, it ...

How can I maintain focus selection while replacing HTML with text in a contenteditable div without losing it?

When working with a div tag that needs to be editable, the goal is to prevent users from entering any HTML into the tag. However, despite efforts to restrict input, when users copy and paste content, it often includes unwanted tags. To address this issue, ...

When attempting to retrieve JSON data for the second time, AJAX fails to fetch the information

After successfully sending an Ajax request to a php file and receiving a JSON array of the submitted data, I encountered an error on the second attempt. The error message reads: SyntaxError: JSON.parse: unexpected end of data at line 1 column 1 of the JSO ...