更改 angularJS 的 karma-jasmine 单元测试中的语言环境

Changing locale in karma-jasmine unit test for angularJS

我正在尝试使用 angular-dynamic-local[=25 为 AngularJS(通过 Karma 运行)更改 Jasmine 单元测试中的语言环境=].

describe('currency filter', function () {
    var currencyFilter;
    var tmhDynamicLocale;

    beforeEach(function () {
        module('tmh.dynamicLocale');

        inject(function ($injector) {
            var $filter = $injector.get('$filter');
            currencyFilter = $filter('currency');
            tmhDynamicLocale = $injector.get('tmhDynamicLocale');
        });
    });

    it('formats US currency in standard form', function () {
        expect(currencyFilter(50.17)).toBe(".17");
    });

    it('formats French Canadian value with $ at end and comma for decimal', function () {
        tmhDynamicLocale.set('fr-ca');
        expect(currencyFilter(50.17)).toBe("50,17$");
    });
});

第二次测试失败:

Expected '.17' to be '50,17$'.

语言环境从未更改过。控制台显示 404 错误:

WARN [web-server]: 404: /angular/i18n/angular-locale_fr-ca.js

似乎 URL 路径在 运行 在浏览器中打开应用程序时被识别,但在 运行 通过 Karma 时无法识别。

我错过了什么?

这是因为 angular-dynamic-locale 在调用 set-method 时正在加载语言环境脚本(在您的情况下为 fr-ca)。 您添加到 karma.conf.js 的文件是从 /base/angular/... 提供的,这就是为什么你得到一个 404。

您可以做的是更改 thmDynamicLocaleProvider 的 localeProviderPattern 以包含基本路径(在模块配置中):

tmhDynamicLocaleProvider.localeLocationPattern('base/angular/i18n/angular-locale_{{locale}}.js');

终于解决了。我们这里有几件事要做。

  1. 我没有在 karma.conf.js 中加载语言环境。我曾尝试在 karma.conf.js 中加载 fr-ca 语言环境,但我删除了该行,因为它正在中断默认(美国)测试。事实证明,我还需要加载 en-us 语言环境(然后在 beforeEach 中重置语言环境,我们将在# 4).

    files: [
        ...
        'bower_components/angular-i18n/angular-locale_en-us.js',
        'bower_components/angular-i18n/angular-locale_fr-ca.js',
        ...
    ],
    
  2. 正如 martinoss 正确指出的那样,我需要更改语言环境位置模式。在货币过滤器的直接测试中,这很困难,因为没有模块可以更改 tmhDynamicLocale 的提供程序。在我的 real-world 情况下,这不是问题,因为我正在测试包装货币过滤器的自定义过滤器。为此 post,我创建了一个 brain-dead 包装过滤器:

    (function() {
        angular
            .module('currencyFilterWrapper', [
                'tmh.dynamicLocale'
            ])
            .config(['tmhDynamicLocaleProvider', function(tmhDynamicLocaleProvider) {
                tmhDynamicLocaleProvider.localeLocationPattern('base/bower_components/angular-i18n/angular-locale_{{locale}}.js');
    }])
            .filter('doCurrency', doCurrency)
        ;
    
        function doCurrency($filter) {
            return function(input) {
                return $filter('currency')(input);
            }
        }
    })();
    
    1. 前两项解决了 404 问题。但是 French-Canadian 语言环境在 $ 符号之前指定了一个 space,所以我将断言更改为 expect(currencyFilter(50.17)).toBe("50,17 $");
      但这也没有用。货币过滤器实际上是插入一个non-breakingspace。所以正确的断言是expect(currencyFilter(50.17)).toBe("50,17\u00A0$");

    2. tmhDynamicLocale.set 是异步的。此外,我们需要在每次测试前将语言环境重置为默认值(美国)。所以这是完整的规范(使用 Jasmine 1.3):

      describe('currency filter', function () {
          var currencyFilter;
          var tmhDynamicLocale;
      
          function setLocale(locale) {
              var localeSet;
      
              runs(function () {
                  tmhDynamicLocale.set(locale)
                      .then(function () {
                          localeSet = true;
                      });
              });
      
              waitsFor(function () {
                  return localeSet;
              }, 'setting locale', 100);
          }
      
          beforeEach(function () {
              module('currencyFilterWrapper');
              module('tmh.dynamicLocale');
      
              inject(function ($injector) {
                  var $filter = $injector.get('$filter');
                  currencyFilter = $filter('doCurrency');
                  tmhDynamicLocale = $injector.get('tmhDynamicLocale');
              });
      
              setLocale('en-us');
          });
      
          it('formats US currency in standard form', function () {
              expect(currencyFilter(50.17)).toBe(".17");
          });
      
          it('formats French Canadian value with $ at end and comma for decimal', function () {
              setLocale('fr-ca');
      
              runs(function () {
                  expect(currencyFilter(50.17)).toBe("50,17\u00A0$");
              });
          });
      });