我如何在AngularJS测试中应用动态位置变化



在使用angular-dynamic-locale的AngularJS应用程序中,我想在不同语言环境中测试Locale依赖的代码。

我试图在异步设置中更改语言环境。在以前的茉莉版本中,这是通过闩锁功能完成的。这些现在被弃用并用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返回的承诺仍然永远悬而未决,设置时间出现了。

查看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并消化/应用根范围,但是LOCALE更改回调仍未执行。

我该如何更改此测试套件中的语言环境?

plunker ,添加了 tmhDynamicLocale中的日志。

似乎没有一种干净的方法,但是我找到了一个黑客的解决方法。

为什么承诺不安定下来

tmhDynamicLocale通过<script>元素加载语言环境文件。当此元素的load事件发射时,它将安排$localeChangeSuccess事件并承诺解决。

在生产中,这效果很好:

  1. 我的代码调用tmhDynamicLocale.set('fr-fr')
  2. 创建了<script>元素
  3. 位置文件已加载;load FIRES
  4. load事件回调中,安排新的回调是异步应用的
  5. 完成的重新测量事件也触发了角度消化循环
  6. 摘要周期运行计划的回调
  7. 此回调可以解决该语言环境变化承诺

在测试中,浏览器事件做不是触发摘要周期,因此发生了:

  1. 我的代码调用tmhDynamicLocale.set('fr-fr')
  2. 创建了<script>元素
  3. 我的测试代码中的任何$timeout S在这里运行,带有空的$$applyAsyncQueue
  4. 位置文件已加载; load fires
  5. load事件回调中,计划将新回调用于异步
  6. 我的代码未通知此;它无法触发新的回调,并且承诺永远依据

因此,触发承诺分辨率无法在角度消化周期内完成,或者至少我看不到如何。

解决方案

由于我们无法分辨何时安排回调,请进行轮询直到为止。与$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. 访问$$私人角度内部词不是一个好主意,并且很可能在版本之间打破。
  2. 不断冲洗可能会干扰其他异步设置。
  3. 如果由于某种原因没有清除间隔,它将在以后的测试中造成各种破坏。

plunker

最新更新