javascript - 如何在 AngularJS 测试中应用动态语言环境更改?
问题描述
在使用 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
永远挂起,并且设置超时。
查看显示语言环境更改的内部结构,但从未实际应用: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
和消化/应用根范围,但仍然没有执行语言环境更改回调。
如何更改此测试套件中的语言环境?
Plunker,为清楚起见添加了日志tmhDynamicLocale
。
解决方案
似乎没有一种干净的方法可以做到这一点,但我找到了一个骇人听闻的解决方法。
为什么承诺没有解决
tmhDynamicLocale
通过<script>
元素加载语言环境文件。当load
此元素的事件触发时,它会安排事件$localeChangeSuccess
并承诺解决。
在生产中,这很好用:
- 我的代码调用
tmhDynamicLocale.set('fr-fr')
<script>
元素已创建- 加载语言环境文件;
load
火灾 - 在
load
事件回调中,一个新的回调被安排异步应用 - 完成请求事件也会触发一个 Angular 摘要循环
- 摘要循环运行预定的回调
- 此回调解决了语言环境更改承诺
在测试中,浏览器事件不会触发摘要循环,所以会发生这种情况:
- 我的代码调用
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();
});
但是有很多缺点:
- 访问 $$private Angular 内部不是一个好主意,并且可能会在版本之间中断。
- 不断刷新可能会干扰其他异步设置。
- 如果由于某种原因没有清除间隔,它将对以后的测试造成各种破坏。
推荐阅读
- java - 将盒子递归打包到容器中的问题
- c++ - `std::unique_XXX` 命名约定背后的基本原理是什么?
- android - 线程“主”java.lang.NullPointerException 中的异常:无法注册 lambda 转储目录
- python - SQLAlchemy .包含不区分大小写的and_查询
- javascript - CSS通配符选择和值检查
- java - 图像路径说即使有权限也无法读取(Android Studio)java
- python - 输入函数中的随机变量
- php - Wordpress 样式表未加载
- java - 我的面板不会滚动并且我的滚动面板没有滑块
- reactjs - axios get() 的异步连接有什么问题?