Previously when I was writing angular apps, I used to do
angular.module('ngApp', ['all', 'required', 'ng*', 'dependencies'])
in my app.js
and then inside services/
and controllers
, I could simply do:
angular.module('ngApp')
I have a repo to demonstrate that.
But then I saw the angular-seed/
, the way implemented was,
in controllers/
angular.module('appControllers', ['dependencies'])...
in services/
angular.module('appServices', ['dependencies'])..
in app.js
angular.module('ngApp', ['ng*', 'appControllers', 'appSrvices'])..
I had no issue with design, infact I thought it was good, since evrything was dependency injected as well as modular.
I have a situation where I have a services/movie.js
that has
angular.module('myAppServices', ['ngResource']).factory(..)
and services/config.js
angular.module('myAppServices').factory(..)
But while writing tests with karma and jasmine. In the karma.conf.js,
I had
files: ['usual', 'bower_components/angular-*.js', 'app/services/**/*.js', '..']
but the problem was config.js got loaded before movie.js and there were errors, myAppServices
is not loaded or mis-spelt.
The way I fixed it was I did:
files: ['..', 'app/services/movie.js', 'app/services/config.js']
I have set up a github repo for this too. Here is the controller test file and here is the karma.conf.
I want to know what can be the possible approaches to take such modular approach, without having to specify the order in which the files are to be loaded for my tests.
And this is my first unit test, and its failing:
Error: Unexpected request: GET https://api.themoviedb.org/3/configuration?api_key=2e329c92227ed8be07944ae447c9426f
Expected GET https://api.themoviedb.org/3/movie/top_rated?api_key=2e329c92227ed8be07944ae447c9426f
It would be helpful if I could get some help in fixing that too.
The test
describe('Controllers', function() {
beforeEach(module('myApp'));
beforeEach(module('myAppServices'));
describe("MoviesCtrl", function() {
var scope, ctrl, httpBackend;
beforeEach(inject(function($httpBackend, $rootScope, _$controller_, Movie, Config) {
httpBackend = $httpBackend;
ctrl = _$controller_;
scope = $rootScope.$new();
}));
it("should return a list of movies", function() {
var data = {results: [{name: "Abc"}, {name: "Def"}]};
httpBackend.
expectGET("https://api.themoviedb.org/3/movie/top_rated?api_key=2e329c92227ed8be07944ae447c9426f").
respond(data);
ctrl('MoviesCtrl', { $scope: scope });
httpBackend.flush()
expect(scope.image).toEqual("https://api.themoviedb.org/3/");
});
});
});
conf. file
module.exports = function(config) {
config.set({
basePath: './',
frameworks: ['jasmine'],
files: [
'app/bower_components/angular/angular.js',
'app/bower_components/angular-mocks/angular-mocks.js',
'app/bower_components/angular-resource/angular-resource.js',
'app/bower_components/angular-route/angular-route.js',
'app/services/movie.js',
'app/services/config.js',
'app/controllers/*.js',
'app/app.js',
'unit-tests/**/*.js'
],
exclude: [
'app/**/*.min.js'
],
preprocessors: {
},
reporters: ['progress'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false
});
};
I have figured out the error in test, I had to mock the other http request for the configuration. thanks to @Phil.
This is my test now:
describe('Controllers', function() {
beforeEach(module('myApp'));
beforeEach(module('myAppServices'));
describe("MoviesCtrl", function() {
var scope, httpBackend;
var config_data = { images: { base_url: "http://tmdb.com/t/p", backdrop_sizes: ["w300", "w500"]}},
movie_data = {results: [{name: "Abc"}, {name: "Def"}]};
beforeEach(inject(function($httpBackend, $rootScope, $controller) {
httpBackend = $httpBackend;
scope = $rootScope.$new();
httpBackend.
expectGET("https://api.themoviedb.org/3/configuration?api_key=2e329c92227ed8be07944ae447c9426f").
respond(config_data);
httpBackend.
expectGET("https://api.themoviedb.org/3/movie/top_rated?api_key=2e329c92227ed8be07944ae447c9426f").
respond(movie_data);
$controller('MoviesCtrl', { $scope: scope });
}));
it("should return a list of movies", function() {
expect(scope.image).toEqual({})
httpBackend.flush();
expect(scope.image.backdrop_size).toEqual("w300");
});
});
});
Although I am not sure if this is the right test to do :P . Something like a VCR would be helpful.
Why use two separate files for 10 lines each? The purpose of writing code in separate files is to keep it understandable and maintainable. It would make sense to keep your module 'myAppServices'
in one file.
If you really need to break down your code in multiple files, you should make use of dependency injection and make them each a separate module (see my patch against your repo). Then the order of loading stops being an issue.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With