I'm running jasmine tests with gulp task and I want to test a directive. Directive itself is a simple toggle button component and requires no dependencies. So, I'm following this tutorial, starting with
beforeEach(module('app'));
beforeEach(inject(function($rootScope) {
scope = $rootScope.$new();
}));
it('does something', function() {
expect(scope).toBeDefined();
});
But the test fails with this obscure log
TypeError: 'undefined' is not an object (evaluating '$window.PUBLISH_SETTINGS.webApiUrl')
Somehow, angular calls seemingly unconnected piece of code from inside my application, which requires $window to be defined. What is happening here? How do I isolate my directive so I won't need to mess with $window?
Related
In Jasmine unit test i am writing I am facing issue related to mocking of services and directive in controller.
I have mocked by $injecting.
var someModelObj
beforeEach(inject(function (_someModel_) {
someModelObj= _someModel_;
}));
TypeError: someModelObj.prepareGetSomeItemsRequestParams is not a function
Please let me know how to solve these type of error.
I try to set up angular controller unit test following this guide, the code is as follows:
describe('ProfileController', function() {
// load haloApp module
beforeEach(module('haloApp'));
it("should have notify_changed in scope", inject(function($controller) {
var scope= {},
ctrl = $controller('ProfileController', {$scope:scope});// inject controller
// expect(ProfileController).not.toBeDefined();
expect(scope.notify_changed).toBe(false);
}));
});
When I run this test case with jasmine, it report the following error:
ReferenceError: module is not defined
I have required angular file before this code snippet. Is there anything I am missing?
The module function is a part of the ngMock module defined in angular-mocks.js. Make sure that file is included when running your tests. See https://docs.angularjs.org/api/ngMock and https://docs.angularjs.org/api/ngMock/function/angular.mock.module
I'm trying to write tests for some AngularJS code, but can't even get a hello world to run. Suppose my code looks like this:
var myApp = angular.module("myApp", [])
myApp.controller("MyCtrl", function ($scope) {
$scope.hello = "world"
})
Then the angular docs here suggest that something like this (using jasmine) should work:
describe("my controller", function () {
it("should say hello", function () {
var $scope
inject(function ($rootScope, $controller) {
$scope = $rootScope.$new()
$controller('MyCtrl', {$scope: $scope})
})
expect($scope.hello).toBe("world")
}
}
Unfortunately, inject does not exist, and there are no hints in the docs as to where to get it. Thus the approach in the docs doesn't work.
Looking slightly farther afield, we find $injector, which can be created by angular.injector. From those docs, it's fairly clear that inject(f) should be $injector.invoke(f). So we stick this at the top of our code and make the change:
$injector = angular.injector(["myApp"])
Unfortunately, this gives the error "Uncaught Error: Unknown provider: $controllerProvider from myApp", which my google-fu seems unable to elucidate.
I had been using this ($injector) previously when I was only testing services, and it works perfectly. It is only when mixed with a controller definition that I get the error. It can handle the controller definition, or the $injector, but not both. To me this suggests some kind of priority conflict or double-initialization, but I can't figure it out.
So what does the "Unknown provider..." error mean, and how do I get my hello world controller test working? If someone can help sort me out, that would be great.
I created for you an skeleton you could use for that concrete controller.
describe('my controller', function() {
var $scope;
beforeEach(module('app'));
beforeEach(inject(function($rootScope, $controller) {
$scope = $rootScope.$new();
$controller('MyCtrl', { $scope: $scope });
}));
it('should contain world', function() {
expect($scope.hello).toBe('world');
});
});
Before each test, you inject your app module and before each test, you creates a new scope and instantiates your controller. Then you just need to write as much tests as you need.
We create a new scope in every tests to have a fresh state. We don't want to modify some $scope in one test and then have another one failing because you modified your $scope earlier.
Plunker: http://plnkr.co/edit/4hHqdsvnVwyUhiezpdhW?p=preview
Write a comment if you have any question.
I'm trying to create some unit tests in Angular using Jasmine being run through Teaspoon. The tests are running, however I have a simple test just to test the existence of a controller that is failing. I have the following test setup.
//= require spec_helper
require("angular");
require("angular-mocks");
var app = require("./app");
describe("My App", function() {
describe("App Controllers", function() {
beforeEach(module("app"))
it("Should have created an application controller", inject(function($rootScope, $controller){
var scope = $rootScope.$new();
ctrl = $controller("ApplicationCtrl", { $scope: scope });
}));
})
})
The require statements are processed by Browserify which is handling my dependencies, but I can also hook into sprockets which I'm using for the spec helper.
Inside the app that is being required, I have
require("angular");
var controllers = require("./controllers");
var app = angular.module("app", [
"app.controllers"
]);
exports.app = app;
When I run this test, I get the following error produced
Failure/Error: TypeError: '[object Object]' is not a function (evaluating 'module("aialerts")')
I've spent quite a while trying to figure this out but I have no idea what's going on. Any help appreciated.
I had the same problem. Change this line:
beforeEach(module("app"))
to:
beforeEach(angular.mock.module("app"))
Browserify uses Node-style require, where module is an object that you can use to export functionality:
console.log(module); // {exports: {}}
angular-mocks.js tries to attach a function to window.module, but that's not possible in Browserify/Node.
Taking a look through the angular-mocks source, it appears that angular-mocks also attaches the module function to angular.mock. So instead of using the global module object, you must use angular.mock.module.
I'm using Yeoman to create an angular project and have modules defined as:
angular.module('angularApp')<br />
.controller('LogOutCtrl', function ($scope) {//do stuff});
Test scripts via Yeoman are as follows:
describe('Controller: LogOutCtrl', function () {
// load the controller's module
beforeEach(module('angularApp', ['ui', 'appSettings']));
var LogOutCtrl,
scope;
// Initialize the controller and a mock scope
beforeEach(inject(function ($controller) {
scope = {};
LogOutCtrl = $controller('LogOutCtrl', {
$scope: scope
});
}));
it('should pass', function () {
expect(2+2).toBe(4); //aka some test
});
});
This is returning as an error via grunt/karma:
Error: Argument 'fn' is not a function, got string
I have looked at a few other ways of writing these as well:
How do I test an AngularJS service with Jasmine?
Any help would be appreciated, as I am new to Angular and Jasmine testing. I believe this is probably an issue with Yeoman's templates for test scripts.
Thanks!
This was an issue with the templates that Yeoman was using. They have been resolved after an update from 1.0 beta.