Руководство по дизайну AngularJS
Раньше, когда я писал приложения angular, я обычно делал
angular.module('ngApp', ['all', 'required', 'ng*', 'dependencies'])
в моем app.js
, а затем внутри services/
и controllers
, я мог бы просто сделать:
angular.module('ngApp')
У меня есть repo, чтобы это продемонстрировать.
Но затем я увидел angular-seed/
, реализованный путь был
in controllers/
angular.module('appControllers', ['dependencies'])...
in services/
angular.module('appServices', ['dependencies'])..
в app.js
angular.module('ngApp', ['ng*', 'appControllers', 'appSrvices'])..
У меня не было проблем с дизайном, infact, я думал, что это хорошо, поскольку evrything была зависимой, а также модульной.
У меня есть ситуация, когда у меня есть services/movie.js
, который имеет
angular.module('myAppServices', ['ngResource']).factory(..)
и services/config.js
angular.module('myAppServices').factory(..)
Но при написании тестов с кармой и жасмином. В файле karma.conf.js
У меня было files: ['usual', 'bower_components/angular-*.js', 'app/services/**/*.js', '..']
но проблема заключалась в том, что config.js был загружен перед movie.js, и были ошибки, myAppServices
не загружен или неправильно записан.
Как я его исправил, я сделал:
files: ['..', 'app/services/movie.js', 'app/services/config.js']
Я установил github repo для этого. Вот файл проверки , и вот karma.conf.
Я хочу знать, какие могут быть возможные подходы к использованию такого модульного подхода, не указывая порядок, в котором файлы должны быть загружены для моих тестов.
И это мой первый unit test и его отказ:
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
Было бы полезно, если бы я мог помочь в исправлении этого.
Тест
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/");
});
});
});
конф. файл
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
});
};
UPDATE
Я выяснил ошибку в тесте, мне пришлось издеваться над другим HTTP-запросом для конфигурации. благодаря @Phil.
Это мой тест сейчас:
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");
});
});
});
Хотя я не уверен, что это правильный тест: P. Что-то вроде видеомагнитофона было бы полезно.
Ответы
Ответ 1
Зачем использовать два отдельных файла по 10 строк? Цель написания кода в отдельных файлах - сохранить его понятным и поддерживаемым. Было бы разумно сохранить ваш модуль 'myAppServices'
в одном файле.
Если вам действительно нужно разбить код в нескольких файлах, вы должны использовать инъекцию зависимостей и сделать их отдельными модулями (см. мой патч против ваше репо). Тогда порядок загрузки перестает быть проблемой.
Ответ 2
Я все еще не нашел решение angular -ish для этой проблемы.
Тем не менее есть два способа справиться с этим.
- Использование RequireJS, как в сообщении блога @Lukasz
а второй - грязный, который я сделал,
-
Написал файл _config.js внутри служб /, контроллеров/, директив /, который имеет, например, angular.module('myAppServices', ['ngResource'])
в службах /,
И в karma.config.js мне пришлось сделать files: ['app/services/_config.js', 'app/controllers/_config.js]
. Хотя проблема все еще остается, потому что я должен указать порядок, в котором должны быть загружены два _config.js
.
Другим способом может быть один файл app/config.js
с
(function() {
angular.module('myAppServices', ['ngResource']);
angular.module('myAppControllers', ['myAppServices']);
}());
а затем выполните files: ['app/config.js', 'app/controllers/**/*.js', 'app/services/**/*.js']
в файле karma.conf.js