Unable to unit test an Angular directive that uses $window - javascript

I've got a bunch of working unit tests for various Angular (1.4.7) directives, and I'm using Karma, Jasmine and Sinon for testing.
I'm trying to add a unit test for a new directive, which is the only directive I currently have that uses $window but I'm seeing a cryptic error in the console output:
TypeError: 'undefined' is not an object (evaluating 'this.proxy.toString')
This error is coming from sinon.js at line 2372.
I'm doing all the 'normal' things in a directive unit test such as creating a fake element that has the directive as an attribute:
testElement = document.createElement('div');
testElement.setAttribute('data-my-directive');
document.body.appendChild(testElement);
And compiling the directive:
$compile(testElement)($scope);
I'm using $provide to try mock the $window object:
module('app', function ($provide) {
$provide.value('$window', { id: 'test' });
});
But as soon as I try to use $window in the file being tested, the error shown above is thrown.
As I say, I have a bunch of other unit tests for other directives, services and controllers working as expected, so everything appears to be setup correctly. It's just this particular test.
Any ideas?

I am not sure if this is the same bug, but just a couple of days ago a fix to similar issue was got solved on sinon github:
https://github.com/sinonjs/sinon/pull/833
Fix contains lines:
var callStr = this.proxy ? this.proxy.toString() + "(" : "";
where the null check is one thing and several other lines.
This fix is at file lib/sinon/call.js in commit 7a18eb5.
I am not sure if this is same, because file is different and so is line, too. Still, this was so interesting that I would try latest sinon version and see if this gets fixed. It may be though, that similar error is in several parts of sinon, if the coder is for example same in both files.

Related

Mocking module dependencies in AngularJS unit tests

I have an angular 1.5 project with many modules and each module may depend on other modules. Trying to unit test say a controller which is part of a module I would do import the module like this:
angular.mock.module('SaidModule');
...then provide and inject its services where needed.
The problem is that SaidModule depends on AnotherModule1, AnotherModule2, AnotherModule3....
angular.module('SaidModule', ['AnotherModule1', 'AnotherModule2', 'AnotherModule3']);
So naturally when I call SaidModule the other modules are also invoked which is out of scope in terms of Unit testing
In the unit test I have tried the following solution
angular.module('AnotherModule1',[]);
angular.module('AnotherModule2',[]);
angular.module('AnotherModule3',[]);
angular.mock.module('SaidModule');
and although for the current unit test I have successfully decoupled the dependencies I have also destroyed
the actual AnotherModule1, AnotherModule2, AnotherModule3 so when its there turn to be unit tested they are
not even visible in the angular project which seems correct to me. as I am using angular.module to define a
new module which just happens to override the actual module.
This solution though is also suggested here mocking module dependencies
In the angular docs it states see angular docs mock module
If an object literal is passed each key-value pair will be registered on the module via $provide.value,
the key being the string name (or token) to associate with the value on the injector.
So it seems to me that the solution is using somehow angular.mock.module somehow to override the dependent
modules but so far I have not found a solution.
Any help much appreciated
By calling angular.module('AnotherModule1',[]) you are redefining the AnotherModule1, which I think is causing your downstream problems. Instead, use $provide for each dependent service. There's no need to mock the dependent modules.
Let's say your controller definition looks like this:
angular
.module('SaidModule', ['AnotherModule1', 'AnotherModule2'])
.controller('SaidController', [
'$scope',
'AnotherService',
function($scope, AnotherService) {
this.anotherService = AnotherService.helper();
}
);
Then your test might look like:
describe('SaidController', function() {
var controller, scope, AnotherService;
beforeEach(module('SaidModule'));
beforeEach(module(function($provide) {
AnotherService = { helper: function() { return 0; } };
$provide.value('AnotherService', AnotherService);
}));
beforeEach(inject(function($controller, $rootScope) {
scope = $rootScope.$new();
controller = $controller('SaidController', {
$scope: scope
});
}));
it('creates controller', function() {
expect(controller).not.toBeNull();
});
});
There's no need to mock the dependent modules, just the dependent services.

Set commentDirectivesEnabled and cssClassDirectivesEnabled to false in Angular

I'm attempting to make some small tweaks to my config to hopefully improve performance slightly. I read through the Angular docs here and they mention disabling comment and CSS class directives. I tried to do so with the below code in my config, but I keep getting TypeError: $compileProvider.commentDirectivesEnabled is not a function or TypeError: $compileProvider.cssClassDirectivesEnabled is not a function errors.
Note: I'm running Angular 1.4.9
'use strict';
angular.module('app')
.config(compilationConfig)
;
compilationConfig.$inject = ['$compileProvider'];
function compilationConfig($compileProvider) {
$compileProvider.debugInfoEnabled(false);
$compileProvider.commentDirectivesEnabled(false);
$compileProvider.cssClassDirectivesEnabled(false);
}
Solved this myself. This functionality was introduced in 1.6.0 so you need to upgrade to take advantage of these methods.

The $routeProvider in Angular can't be found in undefined

I'm following a guide on how to include AngularJS in a MVC project and I got to the point where I'm connecting my controllers (the section's name is Routing).
It seems not to work and when I open the console, I see the following error message.
TypeError: Cannot read property '$routeProvider' of undefined
I've checked all the files in the solution for that string and the only usage of it is in the file where I registered my module. It looks like this.
var CoolApp = angular.module('CoolApp', ["ngRoute"]);
CoolApp.controller('CoolController', CoolController);
var configFunction = function ($routeProvider) {
$routeProvider
.when("/one", { templateUrl: "angularRoute/first" })
.when("/two", { templateUrl: "angularRoute/second" })
.when("/thr", { templateUrl: "angularRoute/third" });
}
configFunction.$inject["$routeProvider"];
CoolApp.config(configFunction);
I have MVC controller class named AngularRouteController and as far I can see, the only place where I'm "dotting" the $routeProvider is in when statements. Commenting them out doesn't resolve my issue, though. Instead, the line that seems to be the cause of the error is this one.
configFunction.$inject["$routeProvider"];
Due to my ignorance with Angular, I can't see why. As a consequence, I have no idea how to solve the problem. Any suggestions would be welcome. I've googled the issue but that didn't give me anything useful (as far I could judge).
The closest hits I've got was this and this one and they didn't make me any wiser. Not even sure if those are relevant to my problem.
I've made sure that I reference the routing package of Angular separately as suggested in this answer. Should I skip ngRoute and go for ui.router? Not sure what that changes for the guide...
It looks like you have to change that line to:
configFunction.$inject = [
"$routeProvider"
];

Make react-router not break Jest (reactJs) tests

I'm currently trying to add Jest tests to a React application (found here).
However, when I run the following test,
/** #jsx React.DOM */
jest.dontMock('jquery');
jest.dontMock('../js/components/CategoryPage.jsx');
describe('Category Page', function() {
var React = require('react/addons');
var TestUtils = React.addons.TestUtils;
var CategoryPage = require('../js/components/CategoryPage.jsx');
it('renders into the page correctly', function() {
// Render the CategoryPage into the document
var categoryPage = TestUtils.renderIntoDocument(
<CategoryPage params={{"category": "tests"}} />
);
expect(categoryPage).toBeDefined();
});
});
I get the following error:
● Category Page › it renders into the page correctly
- TypeError: Property 'makeHref' of object #<Object> is not a function
at Navigation.makeHref (/home/stephen/reps/node_modules/react- router/modules/mixins/Navigation.js:29:25)
at React.createClass.getHref (/home/stephen/reps/node_modules/react-router/modules/components/Link.js:76:17)
at React.createClass.render (/home/stephen/reps/node_modules/react-router/modules/components/Link.js:97:18)
at ReactCompositeComponentMixin._renderValidatedComponent (/home/stephen/reps/node_modules/react/lib/ReactCompositeComponent.js:1260:34)
at wrapper [as _renderValidatedComponent] (/home/stephen/reps/node_modules/react/lib/ReactPerf.js:50:21)
at ReactCompositeComponentMixin.mountComponent (/home/stephen/reps/node_modules/react/lib/ReactCompositeComponent.js:802:14)
at wrapper [as mountComponent] (/home/stephen/reps/node_modules/react/lib/ReactPerf.js:50:21)
at ReactDOMComponent.ReactMultiChild.Mixin.mountChildren (/home/stephen/reps/node_modules/react/lib/ReactMultiChild.js:195:42)
at ReactDOMComponent.Mixin._createContentMarkup (/home/stephen/reps/node_modules/react/lib/ReactDOMComponent.js:260:32)
at ReactDOMComponent.Mixin.mountComponent (/home/stephen/reps/node_modules/react/lib/ReactDOMComponent.js:182:14)
at ReactDOMComponent.wrapper [as mountComponent] (/home/stephen/reps/node_modules/react/lib/ReactPerf.js:50:21)
at ReactDOMComponent.ReactMultiChild.Mixin.mountChildren (/home/stephen/reps/node_modules/react/lib/ReactMultiChild.js:195:42)
at ReactDOMComponent.Mixin._createContentMarkup (/home/stephen/reps/node_modules/react/lib/ReactDOMComponent.js:260:32)
Both my app and the CategoryPage component specifically use react-router. The CategoryPage contains a mixin which uses react-router for authentication. Based on my own debugging, I have found that the error is occurring when Jest tries to call makeHref, one of react-router's built-in methods for Navigation.
To fix this, I first tried calling jest.dontMock('react-router'), but this did not have any effect. The problem seems to be that, by not mocking CategoryPage, jest will automatically and irreversibly include all of its dependecies, unmocked.
Part of the reason this issue is so difficult to solve is because most people using Jest with React seem to not be testing their components, either because they are not as test-focused or because they are using Flux and only testing Stores, Dispatchers, etc. We are not yet using Flux, so this is not an option for us, but may be something we have to transition to in the future.
EDIT 1: The test passes if I remove the jest.dontMock('../js/components/CategoryPage.jsx') but then it is impossible to actually test the functionality of that component.
EDIT 2: When I exclude jest.dontMock('jquery') I get another error related to the mixin I use to create Modals:
Category Page › it encountered a declaration exception
- TypeError:
/home/stephen/reps/js/components/CategoryPage.jsx:
/home/stephen/reps/js/components/Feed.jsx:
/home/stephen/reps/js/components/InvestmentButton.jsx:
/home/stephen/reps/js/components/Modal.jsx:
/home/stephen/reps/js/mixins/BootstrapModalMixin.jsx:
/home/stephen/reps/node_modules/bootstrap/dist/js/npm.js:
/home/stephen/reps/node_modules/bootstrap/js/alert.js: Cannot call method 'on' of undefined
EDIT 3: I have seemingly isolated the bug to react-router's Navigation mixin, where it calls this.context.makeHref. The React team has deprecated this.context since version .9 so I believe this may be the source of the problems. Thus, any work-around or fix for this.context is welcome.
I went ahead and put together a fix which allows you to still use Jest.
https://labs.chie.do/jest-testing-with-react-router/
I ended up figuring this out with some help from the creator of rackt-router after creating the issue found here: https://github.com/rackt/react-router/issues/465 .
I got around this by using Karma and Jasmine to test my application. I then used the stub function makeStubbedDescriptor found here: https://gist.github.com/rpflorence/1f72da0cd9e507ebec29.

Assert module use in nodejs?

Hello everyone I was reading node official documentation, and I've seen the "Assert" module, but don't understand its use, my conclutions up to now are that is like the (try--catch) of some languages, the examples on official documentation are not enough for me to understand the module, could you guys help me please?
These would be used for unit testing.
This module is used for writing unit tests for your applications, you can access it with require('assert').
http://nodejs.org/api/assert.html
The goal of a unit test is to test individual units of your code.
For example, to test a function, you give it the input and know what output to expect. This will isolate that function so you can be sure there is not an error in other parts of your code.
From the Node assert documentation:
The assert module provides a simple set of assertion tests that can be used to test invariants. The module is intended for internal use by Node.js, but can be used in application code via require('assert'). However, assert is not a testing framework, and is not intended to be used as a general purpose assertion library.
A simple use of the assert module would be to prevent a division by zero:
var noDivZero = (dividend, divisor) => {
try {
assert(divisor !== 0, 'DivisionByZeroException')
return dividend / divisor
} catch(e) {
return e.message
}
}
noDivZero(10, 0); // DivisionByZeroException

Categories