Как применить динамическое изменение локали в тестах AngularJS? - PullRequest
0 голосов
/ 15 февраля 2019

В приложении AngularJS, использующем angular-dynamic-locale, я хочу протестировать код, зависящий от локали, в разных локалях.

Я пытаюсь изменить локаль в асинхронной установке.В предыдущих версиях Jasmine это было с функцией защелки ;теперь они устарели и заменены обратным вызовом done.

beforeEach(function (done) {
  inject(function ($injector) {
    tmhDynamicLocale = $injector.get('tmhDynamicLocale');

    console.log('setting locale to French...');
    tmhDynamicLocale
      .set('fr-fr')
      .then(function () {
        console.log('locale set.');
        done();
      })
      .catch(function (err) {
        done.fail('failed to set locale:', err);
      });
  });
});

Обещание, возвращаемое tmhDynamicLocale.set, остается в ожидании навсегда, а время установки истекло.

Просмотр innards из tmhDynamicLocale показывает, что изменение языкового стандарта запланировано, но фактически не применяется:

// This line runs
$rootScope.$applyAsync(function() {
  // But this callback doesn't
  storage[storagePut](storageKey, localeId);
  $rootScope.$broadcast('$localeChangeSuccess', localeId, $locale);
  deferred.resolve($locale);
});

Я пытался вызвать $browser.defer.flush и переварить / применить rootобласть действия, но обратный вызов изменения языкового стандарта все еще не выполнен.

Как изменить языковой стандарт в этом наборе тестов?

Плункер , слоги в tmhDynamicLocale добавлены для наглядности.

1 Ответ

0 голосов
/ 23 февраля 2019

Кажется, нет чистого способа сделать это, но я нашел хакерский обходной путь.

Почему обещание не улаживается

tmhDynamicLocale загружает файл локали через элемент <script>.Когда срабатывает событие load этого элемента, он планирует событие $localeChangeSuccess и разрешение обещания.

В производстве это работает хорошо:

  1. Мой код вызывает tmhDynamicLocale.set('fr-fr')
  2. Элемент <script> создан
  3. Загружен файл локали;load срабатывает
  4. В обратном вызове события load запланировано, что новый обратный вызов будет применен асинхронно
  5. Событие завершенного запроса также запускает цикл углового дайджеста
  6. Цикл дайджеста запускает запланированный обратный вызов
  7. Этот обратный вызов разрешает обещание изменения локали

В тестах события браузера не запускают циклы дайджеста, поэтому это происходит:

  1. Мой код вызывает tmhDynamicLocale.set('fr-fr')
  2. Создается <script> элемент
  3. Любые $timeout s в моем тестовом коде выполняются здесь, с пустым $$applyAsyncQueue
  4. Файл локали загружен;load срабатывает
  5. При обратном вызове события load планируется, что новый обратный вызов будет применен асинхронно
  6. Мой код не уведомлен об этом;у него нет никакого способа вызвать новый обратный вызов, и обещание ожидает навсегда

Так что запуск разрешения обещания не может быть выполнен в цикле дайджеста Angular, или, по крайней мере, я не понимаю как.

Обходной путь

Поскольку мы не можем сказать, когда запланирован обратный вызов, проводите опрос, пока он не будет.В отличие от $interval, setInterval не проверяется в тестах и ​​допускает реальный опрос.

Как только обратный вызов запланирован, $browser.defer.flush запустит его и вызовет разрешение обещания.Он выдает, если нет отложенных задач для очистки, поэтому вызывайте его, только если очередь не пуста.

_forceFlushInterval = setInterval(function () {
  if ($rootScope.$$applyAsyncQueue.length > 0) {
    $browser.defer.flush();
  }
});

Возможно, задачи, отличные от изменения локали, могут быть запланированы.Поэтому мы продолжаем опрашивать, пока обещание не будет выполнено.

tmhDynamicLocale.set('fr-fr')
  .then(function () {
    clearInterval(_forceFlushInterval);
    done();
  })
  .catch(function () {
    clearInterval(_forceFlushInterval);
    done.fail();
  });

Но есть много недостатков:

  1. Доступ к $$ private внутренним внутренним элементам Angular не является хорошей идеей и, вероятно, приведет кперерыв между версиями.
  2. Постоянная очистка может помешать другим асинхронным установкам.
  3. Если по какой-то причине интервал не будет очищен, это повлечет за собой всевозможные разрушения в последующих тестах.

Плункер

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...