Ферментное крепление не перерисовывает обновленные компоненты при изменении реквизита

#reactjs #unit-testing #jestjs #enzyme #mount

Вопрос:

У меня есть один родительский компонент people_form.js с тремя входными полями a. имя пользователя b. имя фамилии c. дата рождения

 // people_form.js

import { fetch } from "request";

fetchDuplicateRecords() {
    const {
      first_name,
      last_name,
      date_of_birth,
    } = this.state;

    if (first_name amp;amp; last_name amp;amp; date_of_birth) {
      const searchParams = {
        first_name: first_name,
        last_name: last_name,
        date_of_birth: date_of_birth,
      };

      // url is fetched in other code.
      fetch(url, searchParams)
        .then(
          (response) => {
            this.setState({
              duplicateRecords: response,
            });
          },
          (err) => {
            this.setState({
              duplicateRecords: [],
            });
          }
        )
    } else {
      this.setState({
        duplicateRecords: [],
      });
    }
}

// few more functions in this file

render(){
    const {
      duplicateRecords,
    } = this.state;

    console.log('check',!_.isEmpty(duplicateRecords));

    return (
      <React.Fragment>
        <form>
          // other child components which are rendered.
          
          {!_.isEmpty(duplicateRecords) amp;amp;
            <DuplicateRecordsFinder
              duplicateRecords={duplicateRecords}
              onInputChange={this.handleInputChange}
              closeDuplicateRecordList={this.handleDuplicateRecordsCloseEvent}
            />}
        </form>
      </React.Fragment>  
    )
}
 

В приведенном выше коде fetchDuplicateRecords выполняется при добавлении трех вышеупомянутых полей
. Ниже приводится request.js код файла.

 // request.js
export function fetch(url, data = {}) {
  return $.ajax({
    url: url,
    method: "GET",
    dataType: "json",
    contentType: "application/json",
    data,
  });
}

// duplicate_records_finder.js

export class DuplicateRecordsFinder extends Component {
  initialState() {
      return {
        duplicateRecordsChunk: _.chunk(
          this.props.duplicateRecords,
          3
        )
      }
  }  

  componentDidUpdate(props) {
    if (this.props.duplicateRecords !== props.duplicateRecords) {
      this.setState(this.initialState());
    }
  }

  render() {
      const { duplicateRecordsChunk } = this.state;
      console.log("i am here");
      console.log("duplicateRecordsChunk", duplicateRecordsChunk);

      return (
        <div
            className="card card-profiles mb-4"
        >
      )
  }
}
 

I am using Jest and Enzyme for unit testing.

  1. When we enter the first_name, last_name and date_of_birth, the
    fetchDuplicateRecords function is triggered.
  2. This makes an ajax call to the backend and set the state.
  3. This state change triggers people_form.js and DuplicateRecordsFinder component is displayed on UI.
  4. Using Jest and Enzyme, I am trying to create this scenario. Below is my unit test.
 // people_form.test.js

import * as request from "request";

beforeEach(() => {
    wrapper = mount(<PeopleForm/>)
  });

test("it should display duplicate records when person already exists", () => {
    // mock fetch (ajax)
    request.fetch = jest.fn().mockReturnValueOnce(new Promise((resolve, reject) => { resolve(duplicateRecords); }))
    
    const firstNameInput = wrapper.find("input[name='first_name']");
    firstNameInput.simulate("change", { target: { value: "First", name: "first_name" } });

    const lastNameInput = wrapper.find("input[name='last_name']");
    lastNameInput.simulate("change", { target: { value: "Last", name: "last_name" } });

    // enter date of birth value.
    const dobInput = wrapper.find("input[name='date_of_birth']");
    dobInput.simulate("change", { target: { value: "08-13-1990", name: "date_of_birth" } });

    // wrapper.setState({ first_name: 'First', last_name: "Last", date_of_birth: "08-13-1990", showDuplicateRecords: true,
    // duplicateRecords: duplicateRecords });

    expect(wrapper.containsMatchingElement(<DuplicatePatientRecordsFinder />)).toEqual(true);
  })
 

When I execute the above test this is the output

 expect(received).toEqual(expected) // deep equality

Expected: true
Received: false

expect(wrapper.find(DuplicateRecordsFinder).length).toEqual(true);

console.log
    check false

      at PeopleForm.render (form/people_form.js:311:13)

  console.log
    check false

      at PeopleForm.render (form/people_form.js:311:13)

  console.log
    check true

    at PeopleForm.render (form/people_form.js:311:13)

  console.log
    i am here

      at DuplicateRecordsFinder.render (form/duplicate_records_finder.js:75:13)

  console.log
    duplicateRecordsChunk [  
        // data here
    ]

 

В соответствии с выводом элемент управления достигает визуализации DuplicateRecordsFinder компонента, но ожидаемая визуализация компонента DuplicateRecordsFinder является ложной, что означает, что дерево компонентов не обновляется.
Однако, если я явно задам first_name, last_name, date_of_birth в состоянии, это даст ожидаемый результат.

Я нашел связанную проблему на github.

Любая помощь или предложение будут высоко оценены