如何在AngularJS测试中应用动态区域设置更改?

问题描述 投票:0回答:1

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

我试图在异步设置中更改区域设置。在以前的Jasmine版本中,这是done with a latch function;这些现已弃用,并替换为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返回的承诺永远存在,并且设置超时。

查看innardstmhDynamicLocale显示区域设置更改已安排,但从未实际应用:

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

我尝试过calling $browser.defer.flush并消化/应用根作用域,但仍未执行语言环境更改回调。

如何更改此测试套件中的区域设置?

Plunker,为了清楚起见添加了tmhDynamicLocale的日志。

javascript angularjs jasmine karma-jasmine
1个回答
0
投票

似乎没有一个干净的方法,但我发现了一个hackish解决方法。

Why the promise doesn't settle

tmhDynamicLocale loads the locale file通过<script>元素。当这个元素的load事件发生时,schedules $localeChangeSuccess事件和承诺决议。

在生产中,这很好用:

  1. 我的代码调用tmhDynamicLocale.set('fr-fr')
  2. <script>元素已创建
  3. 加载语言环境文件; load火灾
  4. load事件回调中,计划以异步方式应用新的回调
  5. 完成请求事件还会触发Angular摘要周期
  6. 摘要周期运行预定的回调
  7. 此回调可解析语言环境更改承诺

在测试中,浏览器事件不会触发摘要周期,因此会发生以下情况:

  1. 我的代码调用tmhDynamicLocale.set('fr-fr')
  2. <script>元素已创建
  3. 我的测试代码中的任何$timeouts都在这里运行,有一个空的$$applyAsyncQueue
  4. 加载语言环境文件; load火灾
  5. load事件回调中,计划以异步方式应用新的回调
  6. 我的代码没有得到通知;它没有办法触发新的回调,承诺永远存在

因此,无法在Angular摘要周期内触发承诺解决方案,或者至少我看不到如何解决。

Workaround

由于我们无法确定何时安排了回调,因此请进行轮询。与$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. 访问$$私有Angular内部结构不是一个好主意,并且很可能在版本之间中断。
  2. 不断刷新可能会干扰其他异步设置。
  3. 如果由于某种原因间隔没有被清除,它将在以后的测试中造成各种各样的破坏。

Plunker

© www.soinside.com 2019 - 2024. All rights reserved.