ReferenceError: module is not defined in jasmine - javascript

When i am running SpecRunner.html, I am getting the following error
ReferenceError: module is not defined
My Controller is
angular.module('mymodule', [])
.controller('mycontroller', ['$scope',
function($scope) {
$scope.employees = [{
name: 'Dick',
address: 'Mumbai'
}, {
name: 'Tom',
address: 'US'
}];
$scope.addEmployee = function() {
$scope.employees.push({
name: $scope.name,
address: $scope.address
});
}
}
])
and my spec is
describe('Employee', function() {
var mycontroller, scope;
beforeEach(module('mymodule'));
beforeEach(inject(function($controller, $scope) {
scope = $rootScope;
mycontroller = $controller('mycontroller', {
$scope: scope
});
}));
it("when employee gets added", function() {
var employeecount = $scope.employees.count;
$scope.addEmployee('xxxx', 'yyy');
var employeecount1 = $scope.employees.count;
expect(employeecount + 1).toBe(employeecount1);
});
});
My SpecRunner.html is
<link rel="shortcut icon" type="image/png" href="lib/jasmine-2.2.0/jasmine_favicon.png">
<link rel="stylesheet" href="lib/jasmine-2.2.0/jasmine.css">
<script src="lib/jasmine-2.2.0/jasmine.js"></script>
<script src="lib/jasmine-2.2.0/jasmine-html.js"></script>
<script src="lib/jasmine-2.2.0/boot.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="../Controller.js"></script>
<script src="spec/myspec.js"></script>
PS: Its my first Unit test in jasmine.

Ok so I've been on this issue all day and finally found why it wasn't working even though I had angular mock script in my spec runner. The order matters here, and this is what worked for me.
<link rel="shortcut icon" type="image/png" href="lib/jasmine-2.4.0/jasmine_favicon.png">
<link rel="stylesheet" href="lib/jasmine-2.4.0/jasmine.css">
<script src="lib/jasmine-2.4.0/jasmine.js"></script>
<script src="lib/jasmine-2.4.0/jasmine-html.js"></script>
<script src="lib/jasmine-2.4.0/boot.js"></script>
<script src="../../lib/angular/angular.js"></script>
<script src="../../lib/angular/angular-animate.js"></script>
<script src="../../lib/angular/angular-route.js"></script>
<script src="../../lib/angular/angular-touch.js"></script>
<script src="../../lib/angular/angular-sanitize.js"></script>
<script src="../../lib/angular/angular-mocks.js"></script>
<!-- include source files here... -->
<script src="../student/data/classesData.js"></script>
<!-- include spec files here... -->
<script src="spec/LMSClassesSpec.js"></script>
I really hope this helps someone in the future

You're referencing window.module from the test code. You need to load angular-mocks in your spec-runner to do that, see https://docs.angularjs.org/api/ngMock/function/angular.mock.module

Related

How to use modal in angularjs ui?

I'm trying to use Angular UI modal, but I keep getting an unknown provider error message: "Error: [$injector:unpr]".
I use custom build to minimize the overall size of the file. I have injected the ui dependency in the app when creating it. The build files are added to the index.html page.
//This is the app.js file
(function() {
angular.module('locatorApp', ['ngRoute', 'ngSanitize', 'ui.bootstrap']);
function config($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
templateUrl: 'home/home.view.html',
controller: 'homeCtrl',
controllerAs: 'vm'
})
.when('/about', {
templateUrl: '/common/views/genericText.view.html',
controller: 'aboutCtrl',
controllerAs: 'vm'
})
.when('/location/:locationid', {
templateUrl: '/locationDetail/locationDetail.view.html',
controller: 'locationDetailCtrl',
controllerAs: 'vm'
})
.otherwise({
redirectTo: '/'
});
$locationProvider.html5Mode(true);
}
angular
.module('locatorApp')
.config(['$routeProvider', '$locationProvider', config]);
})();
//This is the controller file
(function() {
angular
.module('locatorApp')
.controller('locationDetailCtrl', locationDetailCtrl);
/*Inject $routeParams service into controller to protect from minification*/
locationDetailCtrl.$inject = ['$routeParams', '$uibModal', 'locatorData'];
function locationDetailCtrl($routeParams, $uibModal, locatorData) {
var vm = this;
vm.locationid = $routeParams.locationid;
locatorData.locationById(vm.locationid)
.success(function(data) {
vm.data = {
location: data
};
vm.pageHeader = {
title: vm.data.location.name
};
})
.error(function(e) {
console.log(e);
});
vm.popupReviewForm = function() {
alert("Let's add a review");
};
}
})();
<!-- This is the index.html file-->
<!DOCTYPE html>
<html ng-app="locatorApp">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LocatoR</title>
<link rel="stylesheet" href="/bootstrap/css/amelia.bootstrap.css">
<link rel="stylesheet" href="/stylesheets/style.css">
</head>
<body ng-view>
<script src="/angular/angular.min.js"></script>
<script src="/lib/angular-route.min.js"></script>
<script src="/lib/angular-sanitize.min.js"></script>
<script src="/lib/ui-bootstrap-custom-2.5.0.min.js"></script>
<script src="/lib/ui-bootstrap-custom-tpls-2.5.0.min.js"></script>
<script src="/angular/locator.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/
jquery.min.js"></script>
<script src="/bootstrap/js/bootstrap.min.js"></script>
<script src="/javascripts/validation.js"></script>
</body>
</html>
//This is the locatorData service
(function() {
/*Data service for pulling data from the API*/
locatorData.$inject = ['$http'];
function locatorData($http) {
var locationByCoords = function(lat, lng) {
return $http.get('/api/locations?lng=' + lng + '&lat=' + lat + '&maxdist=20');
};
var locationById = function(locationid) {
return $http.get('/api/locations/' + locationid);
};
return {
locationByCoords: locationByCoords,
locationById: locationById
};
};
angular
.module('locatorApp')
.service('locatorData', locatorData);
})();
you should use ng-view on a div inside <body>, so script tags will exist after route template is substituted. Then it would be better to reorganize order of script tags you are adding.
At first non-angular script files, then angular, then your sources
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="/javascripts/validation.js"></script>
<script src="/bootstrap/js/bootstrap.min.js"></script>
<script src="/angular/angular.min.js"></script>
<script src="/angular/locator.min.js"></script>
<script src="/lib/angular-route.min.js"></script>
<script src="/lib/angular-sanitize.min.js"></script>
<script src="/lib/ui-bootstrap-custom-2.5.0.min.js"></script>
<script src="/lib/ui-bootstrap-custom-tpls-2.5.0.min.js"></script>
Then use $uibModal service that you've injected:
vm.popupReviewForm = function() {
$uibModal.open({
template: '...html',
//...config from docs
}).then(function(){console.log('closed successfully');})
.catch(function(){console.log('dismissed modal');});
};
Move your script tag either to below of head tag.
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LocatoR</title>
<link rel="stylesheet" href="/bootstrap/css/amelia.bootstrap.css">
<link rel="stylesheet" href="/stylesheets/style.css">
// Scripts
</head>
or, outside the ng-view :
<body>
<div ng-view></div>
// scripts here
</body>
Ok, I've finally figured it out. The problem was using incompatible versions of Angular JS and Angular UI.

angular.js throws Cannot read property 'then' of undefined

I didn't updated any of my .js files, yet my nested views are not displaying at all (even though they were before) and throw this error in console.
Why is it throwing the error and not displaying my nested views as it was originally?
angular version: 1.6.0-rc.0 (.min.js)
angular-ui-router version: v0.3.1 (.min.js)
app.js
'use strict';
var app = angular.module('app', ['ui.router','controllers','filters']);
app.config(function($stateProvider, $urlRouterProvider)
{
$urlRouterProvider.otherwise('/');
// Initialize states
var homeState =
{
name:'home',
url:'/',
views:
{
'' : {templateUrl: 'partials/home.html'}, // App template that organizes the layout of the panels
'panel#home' : {templateUrl: 'partials/panel.html'} // Reusable panel template for multiple panels within app
}
};
// Register states
$stateProvider.state(homeState);
});
controller.js
'use strict';
var controllers = angular.module("controllers", []);
// Initialize controllers
controllers.controller('panelEvaluateController',function($scope)
{
$scope.header = 'Solve an Equation';
$scope.button = '<button>Solve</button>';
$scope.body = 'partials/panels/evaluate.html';
$scope.tooltip = 'Help';
});
controllers.controller('panelConvertController',function($scope)
{
$scope.header = 'Convert an Integer';
$scope.button = '<button>Convert</button>';
$scope.body = 'partials/panels/convert.html';
$scope.tooltip = 'Help convert';
$scope.bases =
[
{ value : 2 , name : 'Binary'},
{ value : 8 , name : 'Octal'},
{ value : 10 , name : 'Decimal'},
{ value : 16 , name : 'Hex'}
];
$scope.base =
[
{selected : 2},
{selected : 10}
];
});
controllers.controller('panelSolutionController',function($scope)
{
$scope.header = 'Solution';
$scope.button = '<div class="row"><div class="col-sm-6"><button><span class="glyphicon glyphicon-chevron-left"></span></button></div><div class="col-sm-6"><button><span class="glyphicon glyphicon-chevron-right"></span></button></div></div>';
$scope.body = 'templates/panels/solution.html';
$scope.tooltip = 'solve';
});
index.html
<!DOCTYPE html>
<html data-ng-app="app" lang="en">
<head>
<meta charset="UTF-8" name="viewport" content="width=device-width, initial-scale=1">
<title>Show Your Work</title>
<link rel="stylesheet" href="vendor/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="resources/css/specific.css">
</head>
<body>
<div id="header">
<div class="header-color-line"></div>
<div id="logo">Show Your Work</div>
</div>
<div class="row" id="view-container">
<div data-ui-view=""></div> <!-- displays home.html -->
</div>
<script type="text/javascript" src="vendor/jquery/dist/jquery.min.js"></script>
<script type="text/javascript" src="vendor/angular/angular.js"></script>
<script type="text/javascript" src="vendor/angular-ui-router/release/angular-ui-router.js"></script>
<script type="text/javascript" src="vendor/bootstrap/dist/js/bootstrap.min.js"></script>
<script type="text/javascript" src="resources/js/app.js"></script>
<script type="text/javascript" src="resources/js/controllers.js"></script>
<script type="text/javascript" src="resources/js/filters.js"></script>
</body>
</html>
filters.js
'use strict';
var filters = angular.module("filters", []);
filters.filter('trusted', function($sce)
{
return function(val)
{
return $sce.trustAsHtml(val);
};
});
You need to update the ui-router version which should match with the angular version, Now the versions you have mentioned does not match.
<script type="text/javascript" src="vendor/angular/angular.js"></script>
<script type="text/javascript" src="vendor/angular-ui-router/release/angular-ui-router.js"></script>

How can I make NgJsTree apply model updates?

In my project I have included: JQuery, JSTree, Angular and NgJsTree. Whenever I update my treeData model, the data change is not reflected in the tree.
tcwsApp.service('explorerService', ['$http', '$log', '$timeout',
function($http, $log, $timeout) {
var service = this;
service.treeData = {
rootNodes: [{
"text": "Initial node"
}]
};
return ({
getTreeData: getTreeData,
initService: initService
});
function initService() {
getRootNodes();
}
function getTreeData() {
return service.treeData;
}
function getRootNodes() {
var request = $http.get("api/explorer");
request.then(function(response) {
$log.debug(response);
service.treeData.rootNodes = response.data.list;
}, function(response) {
$log.error(response);
});
}
}
]);
tcwsApp.controller('explorerController', ['$log', 'explorerService',
function($log, explorerService) {
var explorer = this;
explorerService.initService();
explorer.treeData = explorerService.getTreeData();
explorer.applyChanges = function() {
return true;
};
explorer.treeConfig = {
core: {
multiple: false,
animation: true,
error: function(error) {
$log.error('treeCtrl: error from js tree - ' + angular.toJson(error));
},
check_callback: true,
worker: true
},
version: 1,
plugins: ['types', 'checkbox']
};
}
]);
tcwsApp.directive('explorerTree', function() {
return {
templateUrl: 'app/template/explorer_tree.html'
};
});
<!DOCTYPE HTML>
<html ng-app="tcwsApp">
<head>
<meta charset="utf-8">
<title>TCWS</title>
<link rel="stylesheet" href="lib/jstree/themes/default/style.min.css" />
<link rel="stylesheet" href="lib/lht-bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="lib/lht-bootstrap/css/bootstrap-theme.min.css">
<link rel="stylesheet" href="app/tcws_app.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="lib/angular-messages.js"></script>
<script src="lib/jstree/jstree.js"></script>
<script src="lib/jstree/ngJsTree.js"></script>
<script src="lib/lht-bootstrap/js/bootstrap.min.js"></script>
</head>
<body>
<tcws-app>
<!-- directive contents pasted -->
<explorer-tree>
<div class="col-md-4" ng-controller="explorerController as explorer">
<div js-tree="explorer.treeConfig" ng-model="explorer.treeData.rootNodes" should-apply="explorer.applyChanges()" tree-events="ready:readyCB;create_node:createNodeCB" tree="explorer.treeInstance">
{{explorer.treeData.rootNodes}}
</div>
</explorer-tree>
</tcws-app>
<script src="app/tcws_app.js"></script>
<script src="app/controller/explorer_tree.js"></script>
</body>
</html>
This displays the initial node - however the debug output via {{explorer.treeData.rootNodes}} is updated correctly after the http.get request finishes.
Resulting web page
Jstree has 2 json formats:
default: node w/ children
alternative: node w/ parent
Automatic updates on model change are only possible with the alternative format as stated here: Github Issue.

Donut chart is not working in angularjs

I am new to AngularJS. I want to create a donut which has onclick function and it goes to next page. I am trying to create a donut but it shows empty page. also console shows no error. I referred this to create a donut here is my code. i tried to merge the working code.
<!doctype html>
<html ng-app="MyApp" >
<head>
<meta charset="utf-8">
<title>AngularJS Plunker</title>
<link href='https://fonts.googleapis.com/css?family=Roboto:400,300,500,700' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" integrity="sha384-fLW2N01lMqjakBkx3l/M9EahuwpSfeNvV63J5ezn3uZzapT0u7EYsXMjQV+0En5r" crossorigin="anonymous">
<link rel="stylesheet" href="style.css">
</head>
<body ng-controller="MyCtrl">
<div ng-app="my.app"
donut-chart
donut-data='[
{label: "Download Sales", value: 12},
{label: "In-Store Sales",value: 30},
{label: "Mail-Order Sales", value: 20}
]'
donut-colors='["#31C0BE","#c7254e","#98a0d3"]'
donut-formatter='"currency"'>
</div>
<script>document.write("<base href=\"" + document.location + "\" />");</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<script src="bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-morris-chart/1.2.0/angular-morris-chart.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular-animate.js"></script>
<script src="app.js"></script>
</body>
</html>
and my js file
var app = angular.module("MyApp", ["ngAnimate"]);
app.controller('MyCtrl', function($scope, $timeout) {
$scope.name = '';
$scope.data = {
singleSelect: null,
multipleSelect: [],
option1: 'option-1',
};
$scope.forceUnknownOption = function() {
$scope.data.singleSelect = 'nonsense';
};
});
angular.module('my.app', [
'angular.morris-chart'
])
Try to change the app.js file to
angular.module('my.app', ['angular.morris-chart'])
.controller('MyCtrl', function($scope, $timeout) {
$scope.name = '';
$scope.data = {
singleSelect: null,
multipleSelect: [],
option1: 'option-1',
};
$scope.forceUnknownOption = function() {
$scope.data.singleSelect = 'nonsense';
};
});
The controller MyCtrl must be a controller of the app my.app.
See http://plnkr.co/edit/AsxnDG?p=preview
Alternatively, you can split up the app definition and the controller definition into two files. Usually, a file app.js is used for the definition of my.app and a file controllers.js is used for the controller definitions.
E.g.:
app.js
var mod = angular.module('my.app', ['angular.morris-chart']);
controllers.js
var mod = angular.module('my.app.controllers', []);
var MyCtrl = function($scope, $timeout) {
...
};
mod.controller('MyCtrl', ['$scope', '$timeout', MyCtrl]);

Jasmine test for Angular can't find my controller

I'm having trouble setting up Jasmine tests for an Angular app. Jasmine can't find my controller (I suspect it can't find my app at all).
Here is a sample that demonstrates the problem I'm running into:
angular.module('testMod', [])
.controller('testController', ['$scope', function($scope) {
$scope.person = {name: 'Jim', age: 14};
function innerFunction() {}
}]);
Test:
describe('testMod suite', function() {
var $rootScope, myController;
beforeEach( inject(function($injector) {
angular.module('testMod');
$rootScope = $injector.get('$rootScope');
var $controller = $injector.get('$controller');
myController = $controller('testController', {$scope: $rootScope});
}) );
it('works', function() {
expect( typeof myController.innerFunction).toBe('function');
});
});
It fails on the line
myController = $controller('testController', {$scope: $rootScope});
The error I'm seeing is:
Error: [ng:areq] Argument 'testController' is not a function, got undefined
I'm using the standalone SpecRunner.html for Jasmine, with my app and spec loaded:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Jasmine Spec Runner v2.0.0</title>
<link rel="shortcut icon" type="image/png" href="lib/jasmine-2.0.0/jasmine_favicon.png">
<link rel="stylesheet" type="text/css" href="lib/jasmine-2.0.0/jasmine.css">
<script type="text/javascript" src="lib/jasmine-2.0.0/jasmine.js"></script>
<script type="text/javascript" src="lib/jasmine-2.0.0/jasmine-html.js"></script>
<script type="text/javascript" src="lib/jasmine-2.0.0/boot.js"></script>
<!-- angular-mock must be loaded AFTER Jasmine -->
<script type="text/javascript" src="../src/angular-1.2.5.min.js"></script>
<script type="text/javascript" src="../src/angular-mock-1.2.5.js"></script>
<!-- include source files here... -->
<script type="text/javascript" src="../src/testMod.js"></script>
<!-- include spec files here... -->
<script type="text/javascript" src="spec/testMod.Test.js"></script>
</head>
<body>
</body>
</html>
Any suggestions are appreciated - I've been struggling with this for a while now.
There are several problems with your test:
You are not injecting scope properly.
You are not using scope properly.
There is a toBeDefined() method to check if function is defined no need to type check.
Change the code in your test to
describe('testMod suite', function() {
var $rootScope, testController;
beforeEach(module('testMod'));
beforeEach(inject(function($controller, $rootScope) {
myScope = $rootScope.$new();
ctrl = $controller('testController', {
$scope: myScope
});
}));
it('works', function() {
expect( myScope.innerFunction).toBeDefined();
});
});
Also, change your angular controller code to:
angular.module('testMod', [])
.controller('testController', ['$scope', function($scope) {
$scope.person = {name: 'Jim', age: 14};
$scope.innerFunction = function() {}
}]);

Categories