使用i18next和故事书进行Jest测试

时间:2018-02-18 00:40:26

标签: javascript reactjs jestjs i18next

我在组件仓库中使用i18next。组件工作正常,但我的测试有问题。我使用i18next with hoc,当我只导出组件时,测试正在传递,但是当我导出它时就像export default translate('components')(List);测试失败。我尝试使用hoc和两个导出,但是在另一个中使用了一些组件,我无法在不使用的情况下导入它。我的架构看起来像:带有I18nextProvider的Root组件,我已经用这个组件包装了故事中的每个组件,它是我主应用程序中的主要组件。看起来就像那样:

const Root = ({ component, i18 }) => (
  <I18nextProvider i18n={i18}>
    <div className={bindClasses('wrapper')}>
      {component}
    </div>
  </I18nextProvider>
);

示例组件:

import React, { Component } from 'react';
import { translate } from 'react-i18next';
import classNameBind from 'classnames/bind';
import styles from './List.css';
import Icon from '../Icon';
import uuid from '../../utils/methods/uuid';

class List extends Component {
  constructor(props) {
    super(props);

    this.state = {
      items: props.items,
    };
  }

  renderNoItems() {
    const { items, t } = this.props;

    return items.length === 0 ?
      t('noMatchingFoundLabel') : '';
  }

  renderItems() {
    const { onItemSelected } = this.props;
    const { items } = this.state;

    return items
      .map(element =>
        (
          <li key={uuid()}>
            <a role="button" tabIndex={0} onClick={() => onItemSelected(element)}>
              { element.icon ? <Icon {...element.icon} /> : '' }
              {element.name}
            </a>
          </li>
        ),
      );
  }

  render() {
    const { className } = this.props;
    const bindClasses = classNameBind.bind(styles);

    return (
      <nav
        ref={(scrollable) => { this.scrollable = scrollable; }}
        className={bindClasses('wrapper', className)}
        onScroll={this.handleScroll}
      >
        <ul>
          {this.renderItems()}
        </ul>
      </nav>
    );
  }
}

export default translate('components')(List);

每个组件都有index.js文件,只有导出默认值。

故事中的用法:

<Root i18={i18}>
    <List />
</Root>

我不确定这里。我应该将t函数传递给List组件吗?它没有它,但也许我应该。 并测试:

import React from 'react';
import List from '../List';
import { shallow, mount } from 'enzyme';
import Icon from "../../Icon";
import TextField from "../../TextField";

describe("List component", () => {
  const defaultPropsWithIcons = {
    items: [
      { name: 'Item1', icon: { name: 'upload', color: 'default' }, options: { some: 'options1'} },
      { name: 'Item2', icon: { name: 'upload', color: 'default' }, options: { some: 'options2'} },
    ],
    t: jest.fn(),
  };

  test("should render List component with passed items with icons", () => {
    const wrapper = shallow(<List {...defaultPropsWithIcons} />);
    const actionList = wrapper.find('.wrapper');

    expect(list.find('ul').children().length).toBe(2);
    expect(list.find('ul').children().at(0).find('a').exists());
     expect(list.find('ul').children().at(0).find(Icon).exists()).toBe(true);
  });

通过正常导出组件,它正常工作,翻译失败。 我试过用

jest.mock('react-i18next', () => ({
    receive the t function as a prop
    translate: () => List => props => <List t={() => ''} {...props} />,
  }));

const wrapper = shallow(<List {...defaultPropsWithIcons} t={key => key} />);

但它没有帮助,仍然在第一次预期时出现错误(预计为2,收到0) 任何人都知道我应该如何测试它?或者我在i18next使用中有错误?我在每个测试中遇到同样的问题,我在另一个组件中使用List组件,或者只在其他组件中使用i18next。

问候

1 个答案:

答案 0 :(得分:0)

您不应该测试HOC中包含的组件,因为单元测试应该测试代码的各个部分。

  

在计算机编程中,单元测试是一种软件测试方法   哪些单位的源代码。   https://en.wikipedia.org/wiki/Unit_testing

尽量避免使用来自jest的{mount},我怀疑你在使用它时会遇到麻烦,因为它会渲染子组件。

如果您想要进行集成测试并渲染ne = sted组件,您可以像这样使用mock:

import { translate } from 'react-i18next';
jest.mock('react-i18next', () => ({
    translate: () => List => props => <List t={() => ''} {...props} />,
  }));

<强>更新

如果您不希望将导入标记为未使用,则可以测试翻译组件:

import { translate } from 'react-i18next';
jest.mock('react-i18next', () => ({
    translate: jest.fn(() => List => props => <List t={() => ''} {...props} />),
  }));

test('should test translation', () => {
    expect(translate).toHaveBeenCalled();
    expect(translate).toHaveBeenCalledWith('components');
  });

希望它会有所帮助,快乐的编码!