创建 Jest 快照时如何阻止 redux-form 或 React 更改 htmlFor 和 id?

How to stop redux-form or React from changing htmlFor and id when creating Jest snapshots?

我有一个用 redux-forms v6 制作的向导表单,它看起来像:

--

index.js - 在本地状态保存页码,连接到应用程序级别状态

PageOne - 用 reduxForm 装饰器包装(形式:'wizForm')

PageTwo - 用 reduxForm 装饰器包装(形式:'wizForm')

--

PageOne 和 PageTwo 都包含呈现表单部分的附加组件(初始字段、车辆信息、驾驶员信息...),并且每个部分为该部分中的每个问题呈现自己的组件。

因为有很多嵌套组件,我想测试 PageOne 和 PageTwo 调用从 index.js 传递的道具,我求助于将 Enzyme 的 mount() 函数与假商店一起使用。我想用 Jest MatchSnapshot() 来比较 index.js 是呈现 PageOne 还是 PageTwo,在单击某些按钮以在页面之间来回移动之后。

问题是当我创建快照时,除了创建 16,000 行快照之外,即使我不做任何更改,快照也永远不会与前一个相匹配。我不确定是 redux-form 还是 React,但 htmlFor 和 id 在快照之间不断变化,测试后测试后测试。

我们也使用 css-modules,但我不认为这是导致问题的原因,我们确实将 Jest 配置为与 css-modules 一起工作,修改 "moduleNameWrapper"模拟 .css 文件。有谁知道如何解决这个问题或我应该去哪里找?

测试:

describe('<VehicleAddition />', () => {
  let props;
  beforeEach(() => {
    props = {
      ...,
    };
  });

it('Renders initially', () => {
    const component = shallow(<VehicleAddition {...props} />);
    expect(toJson(component)).toMatchSnapshot();
  });

  it('Renders <PageTwo> when <PageOne> form is submitted', () => {
    const component = shallow(<VehicleAddition {...props} />);
    expect(toJson(component)).toMatchSnapshot();
    component.find('ReduxForm') // reduxForm HOC wraps the <form> in a <ReduxForm> component
      .first()
      .simulate('submit');
    expect(toJson(component)).toMatchSnapshot();
    expect(component.state().page).toEqual(2);
  });

  it('PageTwoStuffs', () => {
    // Render the form, click 'next', assert it's page two
    // click 'previous'
    jest.enableAutomock();
    const store = createStore(
      combineReducers({
        route: jest.fn(() => Immutable.fromJS({})),
        language: jest.fn(() => Immutable.fromJS({})),
        global: jest.fn(() => Immutable.fromJS({})),
        form: formReducer,
      }),
      Immutable.fromJS({}),
    );
    const component = mount(
      <Provider store={store}>
        <VehicleAddition {...props} />
      </Provider>
    );

    // CAN'T check the state of <VehicleAddition /> because it can only be done on root component, says the error message.
    expect(toJson(component)).toMatchSnapshot();

index.js:

export class VehicleAddition extends React.Component { // eslint-disable-line
  constructor(props) {
    super(props);
    this.state = {
      page: 1,
    };
  }

nextPage = () => {
    this.setState({ page: this.state.page + 1 });
  }

previousPage = () => {
    this.setState({ page: this.state.page - 1 });
}


render() {
    return (
      <div>
        {page === 1 &&
          <PageOne
            {...this.props}
          />
        }
        {page === 2 &&
          <PageTwo
            {...this.props}
          />
        }
      </div>
    );
  }
}

PageOne.js

class PageOne extends React.Component { // eslint-disable-line

render() {
    const {
       ...
    } = this.props;
    return (
      <form onSubmit={handleSubmit}>
        <div>
          <InitialFields
            autoPolicies={autoPolicies}
            changeField={this.changeField}
            getFormValues={getFormValues}
            policies={policies}
            primary={primary}
          />
          <VehicleBeingAddedFields
            changeField={this.changeField}
            getFormValues={getFormValues}
            fetchVehMakes={fetchVehMakes}
            fetchVehModels={fetchVehModels}
            policies={policies}
            vehMakes={vehMakes}
            vehModels={vehModels}
          />
...
    <div className="btn-group btn-group-float-right">
          <button
            type="submit"
            onClick={this.handleClick}
            disabled={pristine || submitting}
            className="btn-primary"
          >
            Next
          </button>
        </div>
      </form>
    );
  }
}

PageTwo.js:

class PageTwo extends React.Component { // eslint-disable-line
  render() {
    const {
      ...
    } = this.props;
    return (
      <form onSubmit={handleSubmit}>
        ...
        <div className="btn-group btn-group-float-right">
          <button type="button" className="btn" onClick={previousPage}>Previous</button>{' '}
          <button type="submit" disabled={pristine || submitting} className="btn-primary">Submit</button>
        </div>
      </form>
    );
  }
}

不断变化的快照部分示例:

我通过从测试用例中传递一个硬编码的 id 值解决了这个问题

import React from 'react';
import renderer from 'react-test-renderer';
import { reduxForm } from 'redux-form';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import { mount } from 'enzyme'
import TodoItem from './TodoItem';
import injectTapEventPlugin from 'react-tap-event-plugin';

function setup() {
    const spy = jest.fn();
    const store = createStore(() => ({}));

    const Decorated = reduxForm({ form: 'testForm' })(TodoItem);
    const props = {
        remove: jest.fn(),
        TodoItemReduxFormInitialName: "fullName",
        snapshotTestId:"4"
    }
    const mockedComponent = <Provider store={store}>
                                <Decorated {...props} />
                            </Provider>;

    const enzymeWrapper = mount(mockedComponent)

    injectTapEventPlugin();

    return {
        props,
        mockedComponent,
        enzymeWrapper
    }
}
describe('TodoItem Component', () => {
    it('should render the snapshot', () => {
        const {mockedComponent} = setup()
        const tree = renderer.create(
            mockedComponent
        ).toJSON();
        expect(tree).toMatchSnapshot();
    });


    //not required as snapshot testing covers it
    it('should render Number', () => {
        const {enzymeWrapper} = setup()
        const fieldProps = enzymeWrapper.find('Field').at(0).props();
        expect(fieldProps.hintText).toEqual('Item Number');
        expect(fieldProps.name).toEqual('fullName.itemNumber');
    });


    //not required as snapshot testing covers it
    it('should render remove button', () => {
        const {enzymeWrapper} = setup()
        const button = enzymeWrapper.find('RaisedButton').at(0).props();
        expect(button.label).toEqual("remove")
    });
});