在使用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
返回的承诺永远存在,并且设置超时。
查看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);
});
我尝试过calling $browser.defer.flush
并消化/应用根作用域,但仍未执行语言环境更改回调。
如何更改此测试套件中的区域设置?
Plunker,为了清楚起见添加了tmhDynamicLocale
的日志。
似乎没有一个干净的方法,但我发现了一个hackish解决方法。
tmhDynamicLocale
loads the locale file通过<script>
元素。当这个元素的load
事件发生时,schedules $localeChangeSuccess
事件和承诺决议。
在生产中,这很好用:
tmhDynamicLocale.set('fr-fr')
<script>
元素已创建load
火灾load
事件回调中,计划以异步方式应用新的回调在测试中,浏览器事件不会触发摘要周期,因此会发生以下情况:
tmhDynamicLocale.set('fr-fr')
<script>
元素已创建$timeout
s都在这里运行,有一个空的$$applyAsyncQueue
load
火灾load
事件回调中,计划以异步方式应用新的回调因此,无法在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();
});
但是有许多缺点: