Usage of spec.js file in AngularJS - angularjs

This might sound a stupid question, but I want to know its answer. What is the spec.js file in AngularJS and what is its use? Is it used for testing purpose?
EDIT- Below is the code of file phone-detail.component.spec.js
'use strict';
describe('phoneDetail', function() {
// Load the module that contains the `phoneDetail` component before each test
beforeEach(module('phoneDetail'));
// Test the controller
describe('PhoneDetailController', function() {
var $httpBackend, ctrl;
var xyzPhoneData = {
name: 'phone xyz',
images: ['image/url1.png', 'image/url2.png']
};
beforeEach(inject(function($componentController, _$httpBackend_, $routeParams) {
$httpBackend = _$httpBackend_;
$httpBackend.expectGET('phones/xyz.json').respond(xyzPhoneData);
$routeParams.phoneId = 'xyz';
ctrl = $componentController('phoneDetail');
}));
it('should fetch the phone details', function() {
jasmine.addCustomEqualityTester(angular.equals);
expect(ctrl.phone).toEqual({});
$httpBackend.flush();
expect(ctrl.phone).toEqual(xyzPhoneData);
});
});
});

Use of spec.js is for writing you unit test cases for your angular application.
We write test cases in angular using Jasmine & Karma.
Jasmine is a Behavior Driven Development testing framework for JavaScript. It does not rely on browsers, DOM, or any JavaScript framework. Thus it's suited for websites, Node.js projects, or anywhere that JavaScript can run.
https://github.com/jasmine/jasmine
Karma is essentially a tool which spawns a web server that executes source code against test code for each of the browsers connected. The results of each test against each browser are examined and displayed via the command line to the developer such that they can see which browsers and tests passed or failed.
https://karma-runner.github.io/1.0/index.html

Question - What is the spec.js file in AngularJS ?
Answer - AngularJS uses Jasmine as a testing framework and tests written in Jasmine are called specs. Filename written related to Jasmine must be .spec.ts, the filename extension convention is adhered by configuration of
karma( the test runner tool ).
Question - what is its use? Is it used for testing purpose?
Answer - Karma the test runner gets the specifications for testing from this file. yes, it is used for testing :)
Reference https://angular.io/guide/testing

Related

AngularJS & mocha: $httpBackend call before each test

I am working with angularjs and writing tests in mochajs.
I implemented multi-language support in my application and now I have the problem, that in many test-cases i get an unexpected request for my language.json
Do you have any idea how to handle this, without adding the "$httpBackend.whenGet(....." for the language-handling to each test?
Both Mocha and Jasmine support root-level hooks (which will affect all describes).
When loaded in the first place in karma, this
angular.module('test-setup', []).run(function ($httpBackend) {
$httpBackend.whenGET(...
});
beforeEach(module('test-setup'));
should provide $httpBackend setup for all specs.

Sails + Angular + Jasmine

I use SailsJS for backend and Angular for front End. So far, they work well. SailsJS backend logic has tests in Mocha. I am trying to add some tests for front end Angular.
Angular's documentation on testing is cryptic to me. After reading its documentation for quite some time, I still have no idea about where to start.
1) Where should I put the unit test code for Angular in a SailsJS project? Now Angular code lives under assets/js. Should I put the test under the same directory, like the following?
assets/js/MyAngularCode.js
assets/js/MyAngularCode_test.js
MyAngularCode.js
(function(){
var myApp = angular.module('myApp', []);
myApp.controller('FirstController', [$scope, function($scope){
//blah blah
}]);
})();
What should I write in MyAngularCode_test.js to test any logic in FirstController?
2) How to run Jasmine tests for any given file directory structure in a SailsJS + Angular project?
How to make "Jasmine init" and "Jasmine" work in such a project. I assume need a Jasmine.json file. But where should it be?
3) For example, I have a file,
FirstTest.js
'use strict';
describe("A suite", function() {
beforeEach(angular.mock.module('myApp'));
it("contains spec with an expectation", function() {
expect(true).toBe(true);
});
});
Where should I put it and what should I do so it will not show the following error
ReferenceError: angular is not defined
Since you want just any opinion...
You can use yeoman for scaffolding; this will help you create pages and directory structure.
Use generator-angular since you are working with angular
yo angular:controller foobar will create files for your controller as well as the test files.
It will create a package.json with a test command (grunt test) which works out of the box.
There is a tutorial here: http://yeoman.io/codelab.html
Just clone this github repo, it's a blank app and uses Angular for the front-end https://github.com/sgress454/angular-on-sails

How can I run common code in tests using Karma + Jasmine + AngularJS?

I'm using Karma to run my unit tests against an AngularJS application. The problem is that I use the ui-router plugin, and the fact that it makes some XHR requests to run the templates forces me to mock those requests. Therefore, I see myself repeating this for every test file:
beforeEach(function($templateCache) {
$templateCache.put('templates/layout.html', '');
$templateCache.put('templates/dashboard/index.html', '');
$templateCache.put('templates/session/login.html', '');
});
How can I run this piece of code for all my unit tests? I tried googling, but no luck. Also, should I be doing this in some other way? Please share your opinions.
Thank you all.
You should look into ng-html2js-preprocessor:
https://github.com/karma-runner/karma-ng-html2js-preprocessor
It will batch up all your templates into a template cache module (that uses $templateCache under the hood) that you can use:
describe('SOMETHING', function() {
beforeEach(module('templates'));

AngularJS unit testing. HttpBackend

I have AngularJS app with unit tests covering it. I added one more http request in .run part of application which checking user authentication. Now about 60% of my tests fails because they found 'unexpected http request'. Even directives tests are fail. How can I avoid running this request in tests? How can I easily mock this request in all tests? Im trying to not to put httpBackend.expect('GET', 'URL') to each test - that's too much work.
Testing with Jasmine + Karma
Thanks. I can give more details if needed.
There are a few ways to do this:
1.) Include a beforeEach that Tim Castelijns suggested but for every spec file
2.) Include the beforeEach in a separate file called app-mocks.js & include in your karma.conf.js (I'm guessing you have one).
karma.conf.js
files: [
'location/of/app-mocks.js',
'src/app/**/*.js'
],
app-mocks.js
(function () {
'use strict';
beforeEach(inject(function ($httpBackend) {
$httpBackend.whenGET('blahblahblah.com/cat/:id/food').respond('');
}));
})();
3.) Separate out user authentication logic from the core app and create an $http wrapper service (suggested). Thus you could have (simplified example):
app.js
angular.module('myApp', ['myApp.services']);
user-service.js
angular.module('myApp.services', [])
.factory('User', function ($http) {
function authenticate() {
// authenticate user
}
return {
authenticate: authenticate
};
});
and same for your directives, controllers, etc. This way, you can unit test all of your components in isolation without having to worry about intertwined logic that is actually specific to one type of functionality. Also, when you do test core app functionality, you can just mock or spy on your User service. In your spec files you would inject only the module & functionality you are testing. So instead of injecting your entire core app module, you would:
To test services
beforeEach(module('myApp.services'));
To test directives
beforeEach(module('myApp.directives'));
etc.
Of Note: When your application starts to get big, I would consider organizing your app components based on feature rather than by type as this example above does.
You can use a beforeEach block to define a call that all tests should expect
var httpBackend;
beforeEach(inject(function(_$httpBackend_) {
httpBackend = _$httpBackend_;
httpBackend.expect('GET', 'URL').respond('');
}
Note the .respond('') I added, an expect call needs this, see the documentation if you want to know why.
This beforeEach functionality comes with the widely used jasmine testing framework.

Cordova + Angular: How to test?

I've just recently started fooling around with Cordova for a mobile App. For now the code base is quite small. I've also used AngularJS to drive my javascript. Now that I have reached a stable state, I would like to investigate ways to unit test the code I just wrote. Thing is, I'm not finding any useful resource for the pair. Angular suggests either Karma (unit) or Protractor (scenarios), but I'm finding quite hard to bootstrap them both with a Cordova App, since this is not supposed to run inside the browser, but within some kind of container where cordova can be loaded. Are there already some good test-driven approaches in the open source market regarding test driven development of hybrid apps?
I think that correct approach would be to have cordova.mocks.js included in tests that will mock out cordova dependencies. And then unittest as usual.
I think there is no way at the moment to test the parts of cordova that would call functionality from plugins.
But you could use Karma or Protractor as you would in the browser (eventually with some mocks for cordova and cordova plugins), which require some additional if conditionals to run the app without a physical device
Ie if (window.cordova && cordova.plugins.thePluginExample) { /* Code that uses plugins [...] */ }
You can use "phonegap server" even if you're using cordova, also you can run on the device with cordova run <platform> --device.
You can track issues on the CLI output of both methods.
To help others who get here with the same question as I did...
You probably don't need to bootstrap with Cordova. Use mocks as stand-ins.
Since Cordova attaches to window, you can write your app code to inject $window and mock cordova with with standard mocking.
Example with mocha / chai:
/**
* Test case for AngularJS module that does something when platform = 'ios'
*/
describe('platform = "ios"', function() {
var $window;
beforeEach('inject', inject(function(_$window_) {
$window = _$window_;
$window.cordova = {
platformId: 'ios',
}
}));
it('verifies cordova mock platform = "ios"', function() {
expect($window.cordova.platformId).to.equal('ios');
});
it('does something', function() {
// ...
});
});

Resources