I'm looking for something that generates a boilerplate jasmine test for an angular controller. It seems you could pull the dependencies for the controller out and drop them into the spec and save some typing. I would be shocked if I were the first person to have this idea but I'm unable to find anything that does this, save a yeomen project that doesn't appear to work.
I've recently published my version of Angular JS unit test generator on npm - tleaf. Basically it tries to parse you source file looking for AngularJS units (controllers, services, etc) to extract information about unit name, module name and unit's dependencies. This information is used to create a unit test file, based on a template for this unit type. There is a default set of templates which have a pretty simple structure, it should be ok for general use. But it is also possible to create and use your own templates to generate unit test files. This is a very first version and I'll be happy to have any feedback.
I don't know of a generator for tests but I have two ideas.
Some editors provide templates for "repeated" code. Like Live Templates for Webstorm. There are multiple projects on github providing jasmine templates for it.
You could also check ng-describe. It removes the boilerplate and makes testing simpler. Here's an example form their github:
ngDescribe({
modules: 'A',
inject: ['$rootScope', 'foo'],
tests: function (deps) {
it('finally a test', function () {
deps.$rootScope.$apply();
expect(deps.foo).toEqual('bar');
});
}
});
I am using yeoman with generator-angular to generate our scripts & tests.
yo angular:directive myDirective
yo angular:service myService
yo angular:controller myController
etc..
will generate both the script and spec templates. I am using Karma and Jasmine.
You could also always write your own yeoman generator.
I found this thing and it does a lot of good gob:
https://www.npmjs.com/package/generator-yosapy
Related
When setting up a unit test suite for an angular application using Karma/Jasmine, is it recommended to include the js with the app module's config function in the test's files?
I've read that it is suggested to exclude this from testing, however that seems awkward because there's often critical setup that happens in the config function that would prevent the application from working.
What's the best practice around this? Create a mock config function that does the same thing in a 'mocked' manner?
I'm running across this issue myself but want to understand the broader strategy:
How do unit test with angular-translate
In my application, I ended up using the following solution:
Define an "appBase" module with all the config and run functions that I want to run when unit-testing and create another "app" module which declares "appBase" module as a dependency and includes all the config and run functions that I don't what to run when unit-testing. Then all my unit tests use the "appBase" module, while the final application uses the "app" module. In code:
angular.module('appBase', ['dependencies'])
.config(function() {
// This one will run when unit-testing. Can also set-up mock data
// that will later be overridden by the "app" module
});
angular.module('app', ['appBase'])
.config(function() {
// This function will only run in real app, not in unit-tests.
});
I can run Jasmine unit tests from the Resharper 8.0 unit test runner.
I have a problem where any Javascript references that are normally in the html page (ie in my case Ext-Js) then I can't use the Resharper test runner, as you don't seem to have access to the HTML page that Resharper uses. (I assume it's generated as I could not locate it on disk)
I was thinking if there is a way to call or load your external library references from the Javascript test file directly instead of via the html page, then I could get this to work. I've not found if that is possible with Javascript (or Ext-Js) yet.
It seems the way to go at the moment is hardcoding include statements as special comments in the suite file (called doc-comments references), e.g.:
// include external files like so:
/// <reference path="/path/to/external-file.js" />
// than write your testing suite as usual:
describe('a silly suite', function() {
it('should test something is happening', function() {
expect(something).toBe('happening');
});
});
See this thread on the ReSharper community, as the source of this recommendation.
I wrote 2 repos for dealing with ExtJS 4 for unit testing using Karma test runner/ Jasmine 1.x and 2.0 versions and dealing with Async Issues: here they are: https://github.com/cgauthier/karma_jasmine_1_extjs4 and https://github.com/cgauthier/karma_jasmine_2_extjs4. The trick to loading external references is to add them as files in your modules declaration.
I am having a problem to figure out how to setup Jasmine with modules from RequireJS.
Basically, I want to test a first view:
it("can load sandbox", function() {
var view = new ItemView();
node = view.render().el;
expect(node).toContain("<li>Test</li>");
});
I don't see that ItemView can be defined as Backbone view, or how to inject Backbone into my tests with requirejs. Now, I see some discussions on using testr.js on one hand, on the other hand, I've found a git repo that does a setup of SpecRunner.js : http://github.com/uzikilon/Todos.git
Ideally, I would just be running
rake jasmine
from my project directory, but how would should Jasmine and Require.js be talking to each other?
Many thanks if someone has feedback, eventually, with a pull request on this experimental repo: https://github.com/mulderp/backbone-require-test
Uzi Kilon, who is the author of the github repo you linked to, wrote an article about how to set the two up together, here.
The other part of your question seems to suggest you want to automate the running of the tests, one way to do that is using PhantomJS the headless webkit implementation. You'll find an article about that here
How is backbone.js is getting loaded in your ItemView? If you define require.js configuration that could be shared between your production code and Jasmine tests. Again there are different ways developers do to achieve this.
I'm starting learning angularJS and find out yeoman is quite useful. But some how the controller/service/model generated by yeoman is not good for minifying later. Because due to what I see through the generated template (service in this case ) we have to inject the service implicitly.
But if we want to minify later, it's recommended to inject explicitly using $inject.
So my question is : Is it correct that what I understand ? If it's not then what is the correct way to inject with generated template from yeoman.
Otherwise, we shouldn't use generated template from yeoman at the moment if we want to do minify later, right ?
Thanks
so yeoman gives you something like this when generating a service
testApp.factory('Thing', function(dep1, dep2) {
return {/*...*/};
});
This is problematic when the code is minified, because the process of minification shortens function parameters, and angular uses them to infer which dependencies to inject.
To inject dependencies I recommend the inline annotation which looks like this
testApp.factory('Thing', ['dep1', 'dep2', function(dep1, dep2) {
return {/*...*/};
}]);
Notice the second argument is an array that lists the proper dependency names and that its final item is a function where such dependencies will be injected.
Edit: The Angular generators for Yeoman now support minification for both JavaScript and CoffeeScript code with the --minsafe flag as shown by #Ramiro
You can use the Yeoman Angular generators with the --minsafe, for example:
yo angular:controller user --minsafe
check other options here:
https://npmjs.org/package/generator-angular
Edit:
A follow up on this. It's now unnecessary to use the --minsafe flag, as yeoman comes with the ngmin app, which automatically converts all applicable code to be minifiable, and then minifies it :)
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);
});
});