React 单元测试 -> 模拟点击 child 调用方法
React unit testing -> simulate click on child to invoke method
假设我在 React 中实现了一个简单的 pexeso 游戏 (for those who do not know pexeso - this is a random pexeso example - not mine)。
目前重要的是,游戏由一个 GameBoard 组件组成,其中显示大量 Card 组件。
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
现在我想为我的代码编写单元测试。目前我正在使用 jest、enzyme 和 chai(我有点不知所措,老实说,我真的对所有疯狂的测试引擎名称感到困惑 :)))。
如何模拟对卡片的点击?我阅读了一些有关间谍和存根的内容,但并没有真正理解 how/when 来使用它们。
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 )
} )
我会欢迎任何评论,我是新手。
基于你的 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,
}
]
});
});
如果你想 select 每个组件分别通过道具,你也可以通过 -
let card = wrapper.find('[name="Olive"]').first();
然后在返回的卡片组件shallow wrapper上类似地模拟点击事件。
另请记住,模拟点击事件将调用 handleFlippedCard
,但它会将关联的事件对象传递给您的处理程序,您必须从接收到的事件对象中获取所需的值。
假设我在 React 中实现了一个简单的 pexeso 游戏 (for those who do not know pexeso - this is a random pexeso example - not mine)。
目前重要的是,游戏由一个 GameBoard 组件组成,其中显示大量 Card 组件。
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
现在我想为我的代码编写单元测试。目前我正在使用 jest、enzyme 和 chai(我有点不知所措,老实说,我真的对所有疯狂的测试引擎名称感到困惑 :)))。
如何模拟对卡片的点击?我阅读了一些有关间谍和存根的内容,但并没有真正理解 how/when 来使用它们。
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 )
} )
我会欢迎任何评论,我是新手。
基于你的 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,
}
]
});
});
如果你想 select 每个组件分别通过道具,你也可以通过 -
let card = wrapper.find('[name="Olive"]').first();
然后在返回的卡片组件shallow wrapper上类似地模拟点击事件。
另请记住,模拟点击事件将调用 handleFlippedCard
,但它会将关联的事件对象传递给您的处理程序,您必须从接收到的事件对象中获取所需的值。