簡體   English   中英

用i18next和Storybook開玩笑

[英]Jest tests with i18next and storybook

我在組件存儲庫中使用i18next。 組件工作正常,但測試有問題。 我將i18next與hoc一起使用,當我僅導出組件時,測試通過了,但是當我導出時,如導出默認轉換(“ components”)(列表); 測試失敗。 我嘗試使用hoc和不使用hoc進行兩次導出,但是在其他組件中使用了某些組件,而沒有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的其他組件中使用的每個測試中,都遇到了相同的問題。

問候

您不應該測試包裝在HOC中的組件,這僅僅是因為單元測試應該測試代碼的各個部分。

在計算機編程中,單元測試是一種軟件測試方法,通過該方法可以對源代碼的各個單元進行操作。 https://zh.wikipedia.org/wiki/Unit_testing

盡量避免開玩笑地使用{mount},我懷疑使用它時會遇到麻煩,因為它會呈現子組件。

如果您想進行集成測試並渲染ne = sted組件,則可以像下面這樣使用模擬:

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');
  });

希望對您有所幫助,編碼愉快!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM