Reputation: 35
I have been stuck on this issue for a bit and have not had success with any other questions on here regarding testing uiRouter with requirejs. I have a fairly basic controller setup that uses the $state.go to transition between states once a button is clicked.
runsController.js
define([],
function() {
"use strict"
var runsController = function($scope, $window, $http, $state) {
function getRuns() {
$http.get($window.apiLinks.runs).success(function(data) {
$scope.runs = data.objects;
}).error(function(data) {
console.error();
console.error(data);
});
}
getRuns();
$scope.refresh = getRuns;
$scope.createRun = function() {
//$state.go('createRun');
}
return ["$scope", "$window", "$http", "$state", runsController];
});
The controller is added to an app that depends on uiRouter.
app.js
define(["angular", "js/controllers/runsController", "js/router", "uiRouter"],
function(angular, runsController, router) {
'use strict'
var appName = "myApp";
var app = angular.module(appName, ["ui.router"]);
app.config(router);
app.controller("runsController", runsController);
function getName() {
return appName;
}
return {
app : app,
getName : getName
};
});
router.js
define(["./controllers/runsController"],
function(runsController){
var routes = function($stateProvider, $urlRouterProvider) {
// For any unmatched url, redirect to /runs
$urlRouterProvider.otherwise("/runs");
// Set up the states
$stateProvider
.state('runs', {
url: "/runs",
templateUrl: "partials/runs.html",
controller: "runsController"
})
.state('createRun', {
url: "/createRun",
templateUrl: "partials/runCreator.html"
});
};
return ["$stateProvider", "$urlRouterProvider", routes];
});
Here's the test I have setup for this controller:
define(["angular", "angularMocks", "js/app", "js/controllers/runsController"],
function(angular, mocks, app, runsController) {
'use strict'
describe('runsController Unit Tests', function() {
var mockApp, scope, httpBackend, objects, state;
objects = [
{rid : 1, filename : "myFile.txt", exitCode : 0},
{rid : 2, filename : "test.zip", exitCode : 0},
{rid : 3, filename : "test2.tar", exitCode : 0}
];
beforeEach(function() {
mockApp = angular.module(app.getName());
});
beforeEach(inject(function ($rootScope, $controller, $httpBackend, $http, $state) {
scope = $rootScope.$new();
window.apiLinks = {"runs" : "/mock/api/runs"};
httpBackend = $httpBackend;
state = $state;
httpBackend.when("GET", "/mock/api/runs").respond({
"objects" : objects
});
$controller(runsController[4], {
$scope : scope,
$window : window,
$http : $http,
$state : $state
});
httpBackend.flush();
}));
it("Get state working in test environment", function() {
});
it("Test that controller automatically gets the runs", function() {
// Because of the way our controller files are setup, we have to specify the
// last element in the array instead of just
expect(scope.runs.length).toBe(3);
});
});
This is currently giving me an error message of: Error: [$injector:unpr] Unknown provider: $stateProvider <- $state
From what I have been reading I believe this means I need to be injecting the dependencies that the controller needs in order to run state, but if I am using the app before every test I run then the dependencies should be in there when the .config() is done right? Can anybody help me figure out what it is I am not seeing with this?
Thanks in advance!
Upvotes: 0
Views: 301
Reputation: 373
I had this same issue this is what I came up with.
This is very important:
karma.conf.js
{
pattern: 'ROOT/TO/YOUR/angular-ui-router/release/angular-ui-router.js',
included: false
},
test-main.js : This is your karma - require - config file
paths: {
// External libraries
'angular': '/base/PATH/TO/YOUR/angular/angular',
'angularMocks': '/base/PATH/TO/YOUR/angular-mocks/angular-mocks',
'uiRouter' : '/base/PATH/TO/YOUR/angular-ui-router/release/angular-ui-router',
.....
shim: {
'angular': { 'exports': 'angular' },
'angularMocks': { deps: ['angular'], 'exports': 'angular.mock' },
'uiRouter' : {deps: ['angular'], 'exports' : 'uiRouter'},
define the module
define([
'angular',
'angularMocks',
'uiRouter',
.....
Now when you set up your beforeEach
BeforeEach(inject(function ($injector){
$state = $injector.get('$state');
....
Hope this helps you out.
Upvotes: 1