反应单元测试 - >模拟点击子项以调用方法

时间:2017-02-07 15:02:32

标签: unit-testing reactjs chai enzyme

说我在react(for those who do not know pexeso - this is a random pexeso example - not mine)中实现了一个简单的pexeso游戏。

现在重要的是,游戏包含一个 GameBoard 组件,其中显示了大量组件。

GameBoard组件具有当前翻转卡片阵列的状态 - this.state.flipped_cards

单击一张卡后,它会调用内部功能(强制卡片翻转)。在这个函数中,GameBoard的handleCardFlip函数用于确定最终的游戏状态。

从GameBoard返回的结果JSX看起来像这样:

<div>
  <Card onClick={this.handleFlippedCard} name="MistyRose" />
  <Card onClick={this.handleFlippedCard} name="Olive" />
  <Card onClick={this.handleFlippedCard} name="MistyRose" />
  <Card onClick={this.handleFlippedCard} name="Olive" />
</div>

handleFlippedCard( flipped_card_text ) {
    if ( this.state.flipped_cards.length < MAX_FLIPPED_CARDS ) {
        this.setState(
            {
                flipped_cards:
                this.state.flipped_cards.concat( [flipped_card_text] )
            },
            () => {
                __resolveGameState.bind( this )()
            }
        )
    }
} // handleFlippedCard

现在我想为我的代码编写单元测试。目前我正在使用开玩笑,酶和柴(我有点不知所措,老实说,我真的很困惑所有疯狂的测试引擎名称:)))。

如何模拟卡片上的点击?我读了一些关于间谍和存根的内容,但并不真正了解如何/何时使用它们。

it.only( 'Removes flipped cards if they match', () => {
        const board = shallow( <GameBoard cardsInput={ cardsInput } /> )
        // reveal first card
        board.setState( { 
            flipped_cards: 
                board.state( 'flipped_cards' ).concat( cardsInput[1] )
        } )

        // reveal second card
        board.setState( {
           flipped_cards: 
               board.state( 'flipped_cards' ).concat( cardsInput[3] )
        } )

        // thought the handleFlipped cards would get invoked here..

        expect( board.state( 'visible_cards' ).length ).to
                .equal( cardsInput.length-2 )
    } )

我会欢迎任何评论,我很反应。

1 个答案:

答案 0 :(得分:1)

基于你的jsx

<div>
  <Card onClick={this.handleFlippedCard} name="MistyRose" />
  <Card onClick={this.handleFlippedCard} name="Olive" />
  <Card onClick={this.handleFlippedCard} name="MistyRose" />
  <Card onClick={this.handleFlippedCard} name="Olive" />
</div>

您可以通过

模拟每个<Card>组件上的点击事件
const wrapper = shallow(
  // Pass the required props to GameBoard component if any
  <GameBoard />
);

wrapper.find('Card').forEach(function (card) {
    let cardName = card.prop('name');
    card.simulate('click', {
        preventDefault: () => {
        },
        target: [
          {
            value: cardName,
          }
        ]
      });
});

如果您想通过道具单独选择每个组件,您也可以通过 -

let card = wrapper.find('[name="Olive"]').first();

然后在返回的卡片组件浅包装器上类似地模拟click事件。

另请注意,模拟点击事件会调用handleFlippedCard但它会将关联的事件对象传递给您的处理程序,您必须从收到的事件对象中获取所需的值。