I am having a hard time figuring out why http.post method is not being called within my tests, which is indicated by the message saying ~ "nothing to flush" as well as adding console.log statements to both the success and the error promise methods.
The api code does work when using the app. This is my first angular controller test so I could be missing something simple.
I have been using David Mosher's example as a template https://github.com/davemo/lineman-angular-template/blob/master/spec/controllers/login_controller_spec.coffee
# controller
"use strict"
angular.module("woddlyApp").controller "SignupCtrl", ($scope, $http, $location) ->
$scope.user = {}
$scope.save = (user, role) ->
user.role = role
$http.post('/users', user)
.success (data, status, headers, config) ->
$location.path '/dashboard'
.error (data, status, headers, config) ->
# tests
'use strict'
describe 'Controller: SignupCtrl', ->
# load the controller's module
beforeEach -> module('woddlyApp')
# Initialize the controller and a mock scope
beforeEach inject ($controller, $rootScope, #$location, #$httpBackend) ->
#scope = $rootScope.$new()
#redirect = spyOn($location, 'path')
$controller 'SignupCtrl', { $scope: #scope, $location: $location }
afterEach ->
#$httpBackend.verifyNoOutstandingRequest()
#$httpBackend.verifyNoOutstandingExpectation()
describe 'Successful signup', ->
beforeEach ->
#$httpBackend.expectPOST('/users', #scope.user).respond(200)
#scope.save(#scope.user, 'member')
#$httpBackend.flush()
it 'redirects the user to the dashboard page', ->
expect(#redirect).toHaveBeenCalledWith '/dashboard'
Error
Chrome 28.0 (Linux) Controller: SignupCtrl Successful signup redirects the user to the dashboard page FAILED
Error: No pending request to flush !
at Error (<anonymous>)
at Function.$httpBackend.flush (/home/chris/projects/personal/woddly/client/app/components/angular-mocks/angular-mocks.js:1195:34)
at null.<anonymous> (/home/chris/projects/personal/woddly/client/.tmp/spec/controllers/signup.js:25:34)
Expected spy path to have been called with [ '/dashboard' ] but it was never called.
Error: Expected spy path to have been called with [ '/dashboard' ] but it was never called.
at null.<anonymous> (/home/chris/projects/personal/woddly/client/.tmp/spec/controllers/signup.js:30:38)
Error: Unsatisfied requests: POST /users
at Error (<anonymous>)
at Function.$httpBackend.verifyNoOutstandingExpectation (/home/chris/projects/personal/woddly/client/app/components/angular-mocks/angular-mocks.js:1228:13)
at null.<anonymous> (/home/chris/projects/personal/woddly/client/.tmp/spec/controllers/signup.js:19:32)
As mentioned in the comments I am using angular 1.1.5 (for the new ng-animate). To get my tests passing I needed to install the angular-mocks 1.1.5.
bower install angular-mocks-unstable
or update the bower.js (or components.js) file and run:
bower install
And update my karma.conf.js file
files = [
JASMINE,
JASMINE_ADAPTER,
'app/components/angular-unstable/angular.js',
'app/components/angular-mocks-unstable/angular-mocks.js', // need unstable here
'.tmp/scripts/*.js',
'.tmp/scripts/**/*.js',
'.tmp/spec/**/*.js'
];
Related
How add cookie to my controller correct?
It`s error when I use $cookie otherwise everything works.
angular.module('app', ['ngCookies']);
app.controller('loginCtrl', function ($scope, $http, $state, Authorization, $cookies) {
$cookies.put('expires', 'example');
});
Error
angular.js:13920 Error: [$injector:unpr]
http://errors.angularjs.org/1.5.8/$injector/unpr?p0=%24cookiesProvider%20%3C-%20%24cookies%20%3C-%20loginCtrl
at Error (native)
at http://localhost:64757/Scripts/angular.min.js:6:412
at http://localhost:64757/Scripts/angular.min.js:43:174
at Object.d [as get] (http://localhost:64757/Scripts/angular.min.js:40:432)
at http://localhost:64757/Scripts/angular.min.js:43:236
at d (http://localhost:64757/Scripts/angular.min.js:40:432)
at e (http://localhost:64757/Scripts/angular.min.js:41:158)
at Object.instantiate (http://localhost:64757/Scripts/angular.min.js:42:24)
at http://localhost:64757/Scripts/angular.min.js:90:32
at q (http://localhost:64757/Scripts/AngularUI/ui-router.min.js:7:14338)
If you go to the url that the error gives you: https://docs.angularjs.org/error/$injector/unpr?p0=$cookiesProvider%20%3C-%20$cookies%20%3C-%20loginCtrl
Your angular app is unable to find your dependency. Did you install the angular cookies file? You can install it with:
npm install angular-cookies
OR
bower install angular-cookies
Also when you declare your angular app you should assign it to a variable then use it for your controllers.
var app = angular.module('app',['ngCookies']);
app.controller('loginCtrl', function ($scope, $http, $state, Authorization, $cookies) {
$cookies.put('expires', 'example');
});
I'm trying to move some config out of the main js file. I'm having problems with the step where I push the http interceptor on the $httpProvider.interceptor array, saying that it is an unknown provider. My interceptor is a factory function that lives in a file in the services directory and is appended to module.exports and required/bundled in with browserify. Currently the app errors with a
angular.js:68 Uncaught Error: [$injector:unpr] Unknown provider: $Provider <- $ <- myHttpInterceptor <- $http <- $templateRequest <-
$route
http://errors.angularjs.org/1.5.3/$injector/unpr?p0=%24Provider%20%3C-%20%2…Interceptor%20%3C-%20%24http%20%3C-%20%24templateRequest%20%3C-%20%24route
I had this working in the main app.js file, but trying to factor it out is proving to be harder than I expected. It looks like $httpProvider is undefinded inside the $httpProvider block.
// in app.js
.factory('myHttpInterceptor', ['$injector', '$location', '$q', '$rootScope', '$', services.myHttpInterceptor])
.config(['$httpProvider', providers.httpProvider])
providers.httpProvider : require('./config/http-provider')
services.myHttpInterceptor : require('./services/myHttpInterceptor')
// in http-provider.js
function httpProvider ($httpProvider) {
$httpProvider.defaults.headers.common = {}
$httpProvider.defaults.headers.post = {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'Accept': 'application/json, text/javascript, */*; q=0.01'
};
$httpProvider.defaults.headers.put = {}
$httpProvider.defaults.headers.patch = {}
$httpProvider.interceptors.push('myHttpInterceptor') // <<-- Fails here in the debugger
}])
module.exports = httpProvider
// in myHttpInterceptor.js
function myHttpInterceptor ($injector, $location, $q, $rootScope, $) {
// I did not put jquery in this project ;)
...
}
module.exports = myHttpInterceptor
Let me know if I can provide more info. Thanks for the help!
Update
It would be unwise for me to include the entire app bootstrap file, because it is quite extensive, but here's a look to see how it starts up:
var angular = require('angular'),
$ = require('./jquery.js');
(function (angular, config, controllers, services, directives, filters, providers, $) {
angular
.module('***', ['ngRoute', 'ngResource', ...])
})(
angular,
//config obj
{...},
// controllers obj
{...}
// etc ...
)
All of the modules required at the top are defined and usable. I can stop the debugger after requiring jquery and it allows me to query the DOM with it in the console.
Using Karma Im back filling tests on a project (someone else wrote the angular app - I have the 'pleasure')...
Project written in coffeescript.
I have the following jasmine test:
'use strict'
describe 'module:file:controller', () ->
$controller = null
$scope = null
$state = null
$stateParams = null
Page = null
File = null
beforeEach (module 'forge')
beforeEach inject(($rootScope, _$controller_, _$state_, _$stateParams_, _Page_, _File_) ->
$scope = $rootScope.$new()
$state = _$state_
$stateParams = _$stateParams_
Page = _Page_
File = _File_
$controller = _$controller_
)
describe 'init', () ->
controller = null
beforeEach () ->
$state = {}
$stateParams = {}
controller = $controller('fileController', {$scope: $scope, $state: $state, $stateParams: $stateParams, Page: Page, File: File})
it 'should set page title to File', () ->
spyOn(Page, 'title')
expect(Page.title).toHaveBeenCalledWith 'Files'
it 'should do something with delete', () ->
spyOn(Page, 'addAlert')
$scope.delete(1)
expect(Page.addAlert).toHaveBeenCalled()
Here is the controller:
forge.controller 'fileController', ($scope, $state, $stateParams, Page, File) ->
# Inject base controller
$injector.invoke BaseController, this, { $scope: $scope, Factory: File }
# Set page title
Page.title 'Files'
console.log $stateParams
console.log $state
# Delete
$scope.delete = (id) ->
Page.addAlert 'success', '[TEST] Deleting file...'
console.log $stateParams
console.log $state
# Delegate actions
switch $stateParams.action
when 'delete' then $scope.delete $stateParams.id
I have a bunch of unit test running fine. The application is built using grunt and all code is compiled into /dist/assets/js/app.js.
My karma config:
module.exports = (config) ->
config.set
files: [
'../../dist/assets/js/app.js'
'../../bower_components/angular-mocks/angular-mocks.js'
'unit/**/**.test.coffee'
'../module/**/test/unit/**/*.unit.coffee'
]
preprocessors:
'unit/**/**.test.coffee': ['coffee']
'../module/**/test/unit/**/*.unit.coffee': ['coffee']
frameworks: ['jasmine']
reporters: ['progress']
browsers: ['Chrome', 'Firefox', 'Safari']
logLevel: 'ERROR'
jasmineNodeOpts:
onComplete: null
isVerbose: false
showColors: true
includeStackTrace: false
defaultTimeoutInterval: 30000
When I run the tests I receive:
Chrome 48.0.2564 (Mac OS X 10.11.3) module:file:controller init should set page title to File FAILED
ReferenceError: $injector is not defined
at new <anonymous> (/Users/usr1/repos/proj/dist/assets/js/forge.js:75397:3)
at Object.instantiate (/Users/usr1/repos/proj/dist/assets/js/forge.js:14449:14)
at /Users/usr1/repos/proj/dist/assets/js/forge.js:19700:28
at /Users/usr1/repos/proj/bower_components/angular-mocks/angular-mocks.js:2170:12
at Object.<anonymous> (/Users/usr1/repos/proj/src/module/file/test/unit/controller/file-controller.unit.js:25:27)
Expected spy title to have been called with [ 'Files' ] but it was never called.
at Object.<anonymous> (/Users/usr1/repos/proj/src/module/file/test/unit/controller/file-controller.unit.js:35:33)
Chrome 48.0.2564 (Mac OS X 10.11.3) module:file:controller init should do something with delete FAILED
ReferenceError: $injector is not defined
at new <anonymous> (/Users/usr1/repos/proj/dist/assets/js/forge.js:75397:3)
at Object.instantiate (/Users/usr1/repos/proj/dist/assets/js/forge.js:14449:14)
at /Users/usr1/repos/proj/dist/assets/js/forge.js:19700:28
at /Users/usr1/repos/proj/bower_components/angular-mocks/angular-mocks.js:2170:12
at Object.<anonymous> (/Users/usr1/repos/proj/src/module/file/test/unit/controller/file-controller.unit.js:25:27)
TypeError: $scope.delete is not a function
at Object.<anonymous> (/Users/usr1/repos/proj/src/module/file/test/unit/controller/file-controller.unit.js:39:23)
Chrome 48.0.2564 (Mac OS X 10.11.3): Executed 63 of 63 (2 FAILED) (1.155 secs / 1.134 secs)
Checked all the paths and that the controllers are presentin teh built app.js file.
At a loss now as to why this message persists and any pointers would be great.
My application was minified - this would prevent this working.
angular injector docs.
I am implementing $firebaseObject in my code. However, when I include $firebaseObject as a dependency in my controller (or service), I immediately receive the following Angular error:
Unknown provider:
My controller:
angular.module('myapp.controllers-account', [])
.controller('AccountCtrl',
function($firebaseObject, $state, $anchorScroll, $location, $rootScope, $stateParams,
OtherDependencies) {
var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com");
// download physicsmarie's profile data into a local object
// all server changes are applied in realtime
$scope.profile = $firebaseObject(ref.child('profiles').child('phsyicsmarie'));
})
Removing the dependency, fixes the issue. What is going on?
Note: I have put firebase as a dependency in my module, as I am using it on other places and it works fine.
You need to register firebase as a module with angular app.
angular.module('myapp.controllers-account', ["firebase"])
Refrences
New to AngularJS but slowly getting going with it and so far I like it. I'm coming from the Java/JSP world so bit of a learning curve!
Anyway, I'm trying to figure out how to send all logging to a server side service.
In my app module config I've overridden the Log implementation and I have this working fine - I have log statements automatically creating simply alerts.
Next step was to send them to the server. I've create a service for this using $resource. I then try to autowire the service into my app module config and this is where I've problems.
It's giving me a circular dependency error which I'm not sure what it means or how to resolve it.
Anyone done anything similar before who may have encountered this problem?
The error I'm seeing is 'Uncaught Error: Circular dependency: $browser <- $httpBackend <- $http <- $resource <- LoggingService <- $log <- $exceptionHandler <- $rootScope'
My app config is:
app.config(['$provide', function($provide) {
$provide.decorator('$log', function($delegate, LoggingService) {
var _info = $delegate.info;
var _error = $delegate.error;
$delegate.info = function(msg){
_info(msg);
};
$delegate.error = function(msg){
_error(msg);
//log.error(msg);
alert('Error:' + msg);
};
return $delegate;
});
}]);
Just trying to pass in my LoggingService results in the error.
My logging service is very simple:
app.factory('LoggingService', ['$resource', function($resource) {
return $resource('http://localhost:port/myservice/logging/', {port: ':8080'},
{
save: {method: 'POST'}
}
);
}]);
Regards,
Kevin.
As per Injecting Dependencies in config() modules - AngularJS
You can only use providers in .config
See registering a service with $provide
https://docs.angularjs.org/guide/services