代码之家  ›  专栏  ›  技术社区  ›  Damon

如何在节点中为使用Jest的测试启用Intl?

  •  0
  • Damon  · 技术社区  · 6 年前

    var IntlPolyfill = require('intl');
    require('full-icu');
    Intl.NumberFormat = IntlPolyfill.NumberFormat;
    Intl.DateTimeFormat = IntlPolyfill.DateTimeFormat;
    
    expect((4000).toLocaleString('fr-ca',{style: 'currency',currency: 'CAD',currencyDisplay: 'symbol'})).toBe('4 000,00 $')
    
    /* test output: 
     Expected: "4 000,00 $"
     Received: "CA$ 4,000.00"
    */
    

    在IE11、Chrome和Firefox中,我得到了预期的结果( "14 337,00 $" )但在诺德我不是。

    我在网上找不到什么帮助,但确实找到了我在这里使用的两个库的参考资料。Jest使用的节点环境需要做什么才能访问适当的Intl函数。函数在那里,但似乎正在返回每个区域设置的美国格式。

    0 回复  |  直到 6 年前
        1
  •  1
  •   RSeidelsohn    5 年前

    首先是我的答案,它立即出现在我的脑海中,解决了这个问题,但事实上它是一个 反模式

    您只需导入节点模块 国际

    import Intl from 'intl';
    import CurrencyFormatter from '../../../js/modules/CurrencyFormatter.js';
    
    describe('CurrencyFormatter', () => {
        let formatter = null;
    
        beforeEach(() => {
            formatter = new CurrencyFormatter(Intl);
        });
    
        test([...]);
    });
    

    在JS中,有条件地使用 模块如果通过Jest:

    export default class CurrencyFormatter {
        constructor(optionalIntl) {
            // Needed for Jest, because it doesn't support Intl natively:
            if (optionalIntl != null) {
                global.Intl = optionalIntl;
            }
            [...]
        }
    
        [...]
    }
    

    这样你就保留了多余的 从生产代码中取出模块,并使其仅可用于Jest测试。但正如您可以清楚地看到的,这意味着调整生产代码的唯一目的是满足测试的需要。这叫做 反模式 . 生产代码应该始终服务于生产需求(以及其他dev的可读性/可理解性,ofc),而不是测试环境。

    因此,你应该遵循第二个解决方案 ,它的优点是可以修复套件中所有类似测试的问题,并且使用的代码更改更少。实际上,它不会更改代码,而只更改配置:

    [编辑:] 反模式 -不要为了通过测试而修改生产代码。但是,有一个更好的选择,使用node模块 full-icu 通过在jest的scripts条目中将其传递给node,即在package.json中执行类似的操作:

    [...]
    "scripts": {
        "test": "node --icu-data-dir=node_modules/full-icu node_modules/jest/bin/jest.js --version --config=./jest.config.js"
    },
    [...]