AngularJS + Testacular / Jasmine unit tests: Executed 0 of 0 SUCCESS - angularjs

I am trying to write unit tests for an AngularJS project. The project is based on angular-seed and uses Testacular to run tests. Every attempt to run test.sh script always ends up with "Executed 0 of 0 SUCCESS".
I tried this super-simple "test":
describe('Testing Jasmine', function() {
console.log('describe');
var test = 'test';
it('should be test', function() {
console.log('it');
expect(test).toEqual('test');
});
});
The result is that only 'describe' is logged, the 'it' part is skipped. When I try the same thing on clean angular-seed clone everything works - so I assume that the testing system itself with Testacular and Jasmine is working correctly.
Our project is based on Rails, but the clean angular-seed that I was testing for comparison is running on Apache so I thought that this might be the difference - messed up paths or something in that Rails project.
But there are no error messages, e2e tests work... and also I assume that if some files were missing or paths were incorrect it would not be able to log that 'describe' in tests - if I understand correctly this means that Jasmine is processing the right file (there are no other dependencies in this pseudo-test). How is it possible that the 'describe' part works just fine and only 'it' part seems to be skipped?
Any hint or help would be appreciated.

If you are doing unit tests, do not include the angular-scenario.js file in your testacular config file. That will break the unit tests.

e2e testing in testacular has a long way to go. I struggled with this for a while. It turns out that the left side of an expect must be one of the methods defined in the angular documentation: http://docs.angularjs.org/guide/dev_guide.e2e-testing.
the following is an example
describe('Testing Jasmine', function() {
it('should be test', function() {
expect(element('foo').count()).toEqual(1);
});
});
Remember, if you dont enter in one of the prescribed method calls into the expect, testacular will not run the 'it'

Also make sure that you have one of these attributes used on page you are testing:
'ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'
Because if function angularInit() won't find element with one of these arguments runner won't start.
This is espcially important if you would like to use angular test runner on webage that does not have ng-app - with current version it just won't work.

Please check the order of the Javascript files.
A similar issue was reported in Testacular and reordering the js files fixed the problem.

Related

Is it possible to use Jasmine without Karma for testing Angular/Node based Nw.js apps?

I've read ton's of tutorials, but I must admit that this testing stuff is still very confusing to me. I have a Nw.js app which (of course) uses NodeJS and also Angular. I've installed the Jasmine test framework globally via npm and wrote an example test which starts with the following lines, and placed it in the spec sub-directory:
describe ( 'Test for my controller', function () {
beforeEach ( module ('module_under_test') );
... and so on ...
});
When running the test by typing jasmine on the cmd line (from the root folder of the app), I get the following error message:
TypeError: module is not a function
I know that I have to include the Angular library somehow. But where? In a normal browser application, it is included in the HTML <script> tag, but I don't have this possibility. I also know that I could write a HTML file, which shows the Jasmine result page after tests have finished, but I would prefer to start Jasmine on the cmd line.
First I thought about adding the angular library to the "helpers" entry in jasmine.json. But it didn't work. The documentation of this file is unfortunately very poor. In the Angular documentation and tutorials it is always mentioned to use Karma. But my understanding is that Karma is only useful for testing with browsers, since it spawns an own webserver. This does not make sense in my case.
Would be great if somebody could give me a hint, thanks!

Running more than 10 tests on karma using jasmine causes: "ERROR: Some of your tests did a full page reload!"

So, this is my first project where I'm using Karma and Jasmine to unit test my angularJS code. Used Yeoman angular generator for the setup.
As soon as I reached 11 tests, I got an error saying "Some of your tests did a full page reload". I'm not doing any tests that would trigger a reload.
Digging deeper I saw the same issue being referenced on Github.
https://github.com/jasmine/jasmine/issues/366 -- (FuzzySockets comments)
The problem seems to stem from a line of code in jasmine-core
https://github.com/jasmine/jasmine/blob/master/lib/jasmine-core/jasmine.js
To avoid overflow of stack, the maximumSpecCallbackDepth is set to 20. And every time currentSpecCallbackDepth exceeds that, further tests are executed on a new stack by using the setTimout function.
This is the line that seems to cause problems and makes karma throw the error. (I've verified this by invoking the setTimeout method in my own unit test, and it threw the same error).
If change the maximumSpecCallbackDepth to 100, my tests run fine, and no errors are thrown at the end
Has anyone seen this issue and know a fix? I'm using the latest versions of karma(0.13.15) and jasmine(2.4.1).
I haven't really messed around too much with the default grunt or karma config that came with yeoman generated ones, except that I'm using the chrome launcher instead of the default phantomJS, so I don't understand how everyone else is not facing the same issue here.
+1 for this issue. As u said, it caused by maximumSpecCallbackDepth limitation, but I didn't find no fix for this issue so far. You probably could track issue here https://github.com/karma-runner/karma/issues/1101 .
One temporary solution is to reduce nested 'describe' block in your project.
I got a similar issue where the angular injections in the global beforeEach stopped working and all tests failed after the 20 limit of maximumSpecCallbackDepth.
During my investigations, I found out that angular-mock doesn't play well with the setTimeout done in jasmine when that limit is reached.
The following code that is given as example everywhere will create a new injector on each test case:
var yourService;
beforeEach(module('app'));
beforeEach(inject(function(_yourService_) {
yourService = _yourService_;
}));
Instead, you could do the following, which will use a single injector and register your modules only once.
var yourService;
module.sharedInjector();
beforeAll(module('app'));
beforeEach(inject(function(_yourService_) {
yourService = _yourService_;
}));
Hope this might help others as it took me almost a week to find out that this was the root cause of the issue and not Jasmine itself like some people think on github.

protractor: onPrepare for different test suites

I have onPrepare in my conf.js file where I log in to the application. My understanding is every time I run 1 or more test suites, it first executes whatever is in onPrepare. This is great, as I use onPrepare to log into the application before running the tests.
Issue is, I don't want to login when I run my login-spec.js suite.
I could first logout before running through login-spec.js, but there must be a more elegant way to do this.
As far as I understand, you need a place for suite-specific preparations.
This is what jasmine can help you with.
For jasmine 2.1 and above, there are built-in beforeAll and afterAll notations:
The beforeAll function is called only once before all the specs in
describe are run, and the afterAll function is called after all specs
finish. These functions can be used to speed up test suites with
expensive setup and teardown.
If you are on an older jasmine version, use a separate jasmine-beforeAll package.

Including angular-scenario.js breaks my Rails Jasmine tests, as in they don't run

I have some Jasmine tests for my (currently) very simple site consisting of a Rails back end and an AngularJS front end. I'm trying to do some Jasmine end-to-end testing, but including angular-scenario.js makes my tests not run. It doesn't make them fail. It makes them not start at all.
I'm using version 1.0.7, and all the Angular files are from the same version (and all from the official Angular site. The version of Rails I'm using is 3.1.3 with Ruby 1.9.3. I'm also using the jasmine gem version 1.3.2 and jasmine-rails 0.4.5.
spec/javascripts/support/jasmine.yml:
src_files:
- assets/application.{js,coffee}
stylesheets:
- stylesheets/**/*.css
helpers:
- helpers/**/*.{js,coffee}
- lib/angular-scenario.js
spec_files:
- '**/*[sS]pec.{js,coffee}'
src_dir: 'app/assets/javascripts'
spec_dir: spec/javascripts
spec/javascripts/spec_helper.coffee:
#= require angular.min
#= require angular-mocks
spec/javascripts/templates/brands/index_spec.coffee:
describe 'test', () ->
it 'works', () ->
expect(true).toEqual(true)
Of course, that's just a placeholder until I can get the test work correctly with angular-scenario.js in place.
Without angular-scenario.js, the tests run. With it, nothing.
To test, I typically run RAILS_ENV=test rake spec:javascript, but I've also tried from the web server interface.
The output without angular-secnario.js:
Starting...
Finished
-----------------
1 spec, 0 failures in 0.005s.
ConsoleReporter finished
The output with angular-scenario.js:
Starting...
Finished
-----------------
0 specs, 0 failures in 0s.
ConsoleReporter finished
Things I've tried:
Moving angular-scenario.js to vendor/assets/javacripts and requiring it from spec_helper.coffee.
Removing either other Angular-related requirement from spec_helper.coffee.
angular-scenario.js comes with jQuery packaged with it. Commenting out the jQuery bit, oddly enough, makes the tests run, though they fail because angular-scenario needs jQuery, apparently. I also tried commenting out the jQuery in angular-scenario and including jQuery from the jquery-rails gem. (That was a shot in the dark. I didn't think that would actually work.)
Thank you very much to whoever wants to take a swing at this one.
Jasmine and angular-scenario.js (e2e runner) are two different things and they should be run separately. Angular e2e test framework uses syntax which is very similar to jasmine. Probably when you include it along with jasmine it overrides some jasmine's methods like describe, it and beforeEach.

Loading mocks into an AngularJS unit test

I'm trying to setup my AngularJS application to test out controllers, routes, templates and so on, but I'm having an issue getting some of the helper methods provided by the angular-mocks.js to work (namely module and inject).
I'm using testacular to load up the test suite with the following files added before the specs:
files = [
MOCHA,
MOCHA_ADAPTER,
'../application/lib/angular.min.js',
'./lib/angular/angular-mocks.js',
'./lib/angular/angular-scenario.js',
'../application/application.js',
'./lib/chai.js',
'./lib/chai-should.js',
'./lib/chai-expect.js',
'./spec/**/*.js'
];
So far so good, but when I run the tests I get this issue:
ReferenceError: Can't find variable: module
Not sure where this is loaded. Am I missing something?
First thing to check is that all those files are getting loaded in the test browser. It's surprisingly easy to get a path wrong in your config and not realize it. If you're running testacular with autowatch, you can navigate to http://localhost:9876/context.html with a browser and use developer tools inspect elements/resources/network and see if anything is missing.
If everything is good there and you're still having problems, post some of your test code and I'll take a look.
UPDATE: It appears (strangely) from the comments in the source for angular-mocks.js (line 1635) that window.module is only available with Jasmine. It looks like you're using Mocha instead of Jasmine. This is very likely the culprit.
ANSWER:
I can't rightly take credit for this Matsko, since you figured it out yourself... but it turns out that the current AngularJS stable download and angular-seed contain an older version of ngMock that doesn't support Mocha. Manually replacing the mock file with the latest from the github repo solves the problem. Glad I could help ;-)
I ran into this issue today and I wanted to provide others with a complete summary of the required steps to get this working. First let's say you have a module named myApp. Inside that that module there is a service called myModel. the myModel service has a method named getItems().
Currently, the angular-mocks.js (I am using AngularJS 1.0.6) does not support Mocha. You will need to visit this link and replace the 1.0.6 version with the one in the master branch from the AngularJS GitHub project. An easy way to do this (if you have wget) is wget https://raw.github.com/angular/angular.js/master/src/ngMock/angular-mocks.js in the correct directory. If you use a properly configured Sublime or vim it can also easily pull it down for you.
Make sure your karma.conf.js file includes the angular-mocks.js file in files array
Somewhere in your tests.js file (maybe at the top level describe) include beforeEach(module('myApp')); or whatever you named your main module.
If you plan to use the service (or whatever you want to include in the test) in more than one place you can call another beforeEach where needed like this:
beforeEach(inject(function(myModel) {
mymodel = myModel;
}));
otherwise you just can inject where it is needed. Now the mymodel variable (notice this is the variable you assigned in the beforeEach above) will be available to you for testing in your next blocks. For example, you can now write:
describe('when fetched', function() {
it('should return 3 items', function() {
// console.log(mymodel.getItems());
expect(mymodel.getItems()).to.have.length(3);
});
});

Resources