Как использовать несколько вызовов $timeout.flush() и $httpBackend.flush() в спецификации Jasmine для AngularJS (с PhantomJS) без получения ошибки $digest

Я пытаюсь написать модульный тест для службы AngularJS с Karma и Jasmine, используя браузер PhantomJS. Служба, которую я хочу протестировать, использует вложенные промисы (для чтения базы данных IndexedDB, получения ответов от сервера и записи ответа обратно в базу данных).

То же самое необходимо сделать при записи в базу данных (записать локальную базу данных, отправить/поместить на сервер, обновить локальную базу данных с помощью идентификатора сервера). Все тесты, которые я пишу, работают, кроме тестов на обработку потери соединения с сервером.

Когда это происходит, метод sync() устанавливает онлайн-статус в false и создает $timeout, который многократно проверяет наличие соединения, выполняя рекурсивный вызов. Если соединение снова установлено, все несинхронизированные данные будут синхронизированы (и промисы соответствующих вызовов sync() будут разрешены).

describe('Harmonized', function() {
var ... // setting all 'global' variables

[...] 

beforeEach(function(){
  // Address that the service sends a ping to check if online again
  pingGet = backend.when('GET', 'http://localhost:2403');
  pingGet.respond(0);

  testTablePut121 = backend.when('PUT', 'http://localhost:2403/test_table/121');
  testTablePut121.respond(function(method, url, data, headers) { ... } // returns 200

  [...]
}

[...]

it('should try to sync a SAVED element but should fail because of missing server connectivity', function() {
  var list;
  var timeoutCounter = 0;
  _checkOnline = harmonized._checkOnline; // harmonized is the service that has to be testet
  harmonized._checkOnline = function () {
    // only call the original function two times
    if (timeoutCounter++ < 2) {
      _checkOnline();
      // flush the $timeout and the $httpBackend
      timeout.flush(2000);
      backend.flush(1);
      // this also gives me an error because of the $digest already in progress
      console.log('after tick');
    }
  };


  all.getList().then(function(entries) {
    list = entries;

    testTablePut121.respond(0);
    pingGet = backend.expect('GET', 'http://localhost:2403');
    pingGet.respond(0);

    spyOn(list[0], 'sync').and.callThrough();
    list[0].save().then(
    // resolve is called when the server call was successfull
    function() {
      expect(list[0]._synchronized).toBeTruthy();
      expect(list[0].sync.calls.count()).toBe(2);
      console.log('done');
    }, 
    // reject is called when the server response an error other than 0 (which is not the case in this test spec)
    null, 
    // notify is called when the local db save is made
    function(){
      expect(list[0].sync.calls.count()).toBe(1);
      expect(list[0]._synchronized).toBeFalsy();
    });
    backend.flush(1);
  });
  backend.flush(1);
});

Когда функция backend.flush() вызывается во второй раз (чтобы сбросить http-запрос, сделанный в функции save(), я получаю сообщение об ошибке, говорящее мне, что $digest уже выполняется. Пропустив строку, не сбрасывать запрос (и также получить ошибку из-за этого).

Есть ли способ сбросить все в нужное время, не получая ошибки $digest?


person Simon Jentsch    schedule 16.03.2015    source источник
comment
Кажется, я спросил то же самое и получил ответ. stackoverflow.com/questions/25210951/   -  person FlavorScape    schedule 09.04.2015