имитация щелчка от родителя для ребенка в фермент - PullRequest
0 голосов
/ 28 марта 2019

как я могу перейти к дочернему компоненту и симулировать щелчок.

// родительский компонент

_handleChildClick = () => {
      this.setState({
        enabled: false
      })
    }

    <div>
      <Child 
     onChildClick={this._handleChildClick}
    />
    </div>

// дочерний компонент

<div>
  <button className="toggle"
    onClick={props.onChildClick}
  ></button>
</div>

// test.js

const renderedComponent = shallow(<Parent />)
console.log(renderedComponent.debug()) // i am not able to drill down
// renderedComponent.find('toggle').simulate('click') wont work !!!

если я использую mount, так как мой компонент сначала вызывает какой-то API, он будет иметь компонент загрузчика

даже я попробовал с приведенным ниже фрагментом, родитель даже не приходит

it('test with mount', async () => {
   const a = await mount(<Parent />)
   console.log(a.debug()) // showing the loader only
})

как я могу решить эту проблему, Любая помощь приветствуется:)

// App.js

import React, {Component, Fragment} from 'react'
import Child from './child'

class App extends Component{

  state = {
    data: null,
    enable: false
  }

  componentDidMount(){
    this.getData()
  }

  getData = async () => {
    const response = await fetch('http://www.example.com');
    const data = await response.json();
    this.setState({
      data
    })
  }

  _handleChildClick = () => {
    this.setState({
      enable: true
    })
  }

  render(){
    const {data, enable} = this.state
    if(!data){
      return (
       <div>
         Loading
       </div>
      )
    }else{
      <Fragment>
        <Child
         handleChildClick={this._handleChildClick}
        />
      </Fragment>
    }
  }
}


export default App


import React from 'react';

const child = () => {
  return(
    <div>
      <button
        className="toggle"
        onClick={props.handleChildClick}
      >
      Toggle
      </button>
    </div>
  )
}

export default child

// App.test.js

import React from 'react';
import {enzyme} from 'enzyme';
import App from './App';

describe("App test cases", () => {
  it('should trigger _handleChildClick', async () => {
    window.fetch = jest.fn().mockImplementation(() => ({
      status: 200,
      json: () => new Promise((resolve, reject) => {
        resolve(
            {
              name: "some data"
            }
        )
      })
    })) 
    const mountWrapper = await mount(<App />)
    mountWrapper.update()
    console.log("mountWrapper", mountWrapper.debug()) // showing the loader one
    setTimeout(() => {
      console.log("mountWrapper", mountWrapper.debug()) // nothing showing
      // expect(mountWrapper.find('.toggle').length).toEqual(1)
    },0)
  })
})

1 Ответ

0 голосов
/ 28 марта 2019

Неглубокий рендеринг (который вы используете для своих текущих тестов) отображает только один уровень глубины .Это означает, что вы не сможете смоделировать метод render() или поведение дочерних компонентов с помощью поверхностного средства визуализации.См. Документацию здесь для получения дополнительной информации.

Если вы хотите эффективно выполнить модульное тестирование этого примера кода, вам не следует пытаться смоделировать его дочернее поведение.Вместо этого вы должны проверить <Parent /> и <Child /> отдельно.Это предотвращает изменения в вашем Child компоненте, влияющие на результаты теста в вашем Parent компоненте, или наоборот.Это почти вся причина существования мелкого рендера!Из документации:

Мелкий рендеринг полезен, чтобы ограничиться тестированием компонента как модуля и , чтобы убедиться, что ваши тесты не косвенно утверждают поведение дочерних компонентов .

Я бы написал этот тест для дочернего компонента, используя фиктивную функцию для его свойства onChildClick:

test('triggers its onChildClick prop when clicked', () => {
    const mock = jest.fn()
    const wrapper = shallow(<Child onChildClick={mock} />)
    wrapper.find('.toggle').simulate('click')
    expect(mock).toHaveBeenCalledTimes(1)
})

И я бы написал этот тест для родителя, передавданные, обеспечивающие визуализацию ребенка:

test('sets its state when its child is clicked', (done) => {
    const wrapper = shallow(<App data={{ test: 'test' }}/>)
    expect(wrapper.state('enable')).toBe(false)

    wrapper.find('Child').props().onChildClick()
    expect(wrapper.state('enable')).toBe(true)
})

Только что попробовал оба этих теста, и они работают нормально.Я тестирую полную функциональность компонентов здесь, за исключением того, что процесс разделен на блоки.Дочерний элемент запускает свой объект onChildClick при нажатии кнопки, и запуск этого свойства внутри родительского элемента устанавливает состояние enable в true.

Рендеринг Full-DOM (с mount(<Parent />)) - это очень многоболее грязный, и я действительно считаю его полезным только для тестирования компонентов, использующих API DOM (что в любом случае не должно происходить в React).Чтобы получить более подробное объяснение, загляните в документацию еще раз!

Если вы хотите протестировать более масштабные функции вашего приложения (что похоже на то, что вы делаете), я бы предложил использоватьСквозная среда тестирования, такая как Cypress .

И еще одна вещь ... вы используете wrapper.find('toggle'), но если вы хотите найти узел по его className, тогда вам нужно сделать wrapper.find('.toggle').

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...