Руководство по дизайну 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

а второй - грязный, который я сделал,

  1. Написал файл _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