我正在使用故事书来可视化模拟用户与酶交互后对 React 组件的更改。举个小例子,我想要一个故事,在单击其中一个按钮后显示组件。
我遇到的问题是组件的构造函数被调用了两次:一次是当组件由酶安装时,然后在故事书显示组件时。这会将组件恢复到其默认状态,因此模拟用户交互后的任何更改都将丢失。
下面是一些显示该问题的代码。故事加载后,按钮组件处于"未单击"状态,即使使用酶模拟了单击:
import React from 'react';
class SampleComponent extends React.Component {
constructor(props){
super(props);
console.log('constructor');
this.state = {isClicked: false};
this.onClick = this.onClick.bind(this);
}
onClick(){
console.log('onClick');
this.setState({isClicked: true});
}
render(){
const text = (this.state.isClicked)? 'Clicked!' : 'Not Clicked';
return (
<div>
<input type='button' value='Click' onClick={this.onClick} />
<p>{text}</p>
</div>
);
}
}
export default SampleComponent;
故事文件:
import React from 'react';
import { storiesOf } from '@storybook/react';
import { mount } from 'enzyme';
import { specs, describe, it } from 'storybook-addon-specifications';
import SampleComponent from '../src/SampleComponent';
storiesOf('SampleComponent', module)
.add('clicked', () => {
const comp = <SampleComponent/>;
specs(() => describe('clicked', function () {
it('Should display clicked state message', function () {
const output = mount(comp);
output.find('input').simulate('click');
});
}));
return comp;
});
控制台的输出将是:
constructor
onClick
constructor
您需要取回底层组件实例。这将执行您想要的操作:
storiesOf('SampleComponent', module)
.add('clicked', () => {
let output;
specs(() => describe('clicked', function () {
it('Should display clicked state message', function () {
output = mount(<SampleComponent />);
output.find('input').simulate('click');
});
}));
const Inst = () => output.instance();
return <Inst />
});
我一直在尝试使用故事板和模拟("点击"(并遇到了类似的问题。我永远不会在故事书窗格中看到单击后的状态。 我发现mount(comp(正在将comp渲染到一个单独的DOM - 而不是故事书正在使用的那个。当您返回 comp 时,comp 会在浏览器中呈现,这就是您看到的。 这可能是我尚未弄清楚的配置问题。 我正在使用 https://www.npmjs.com/package/storybook-addon-specifications#using-enzyme 中描述的 webpack 配置
这完成了您正在尝试做的事情,无需使用酶:
storiesOf('SampleComponent', module)
.add('clicked', () => {
const comp = <SampleComponent/>;
setTimeout(()=>{ // let Storybook render comp and then come back
let input=document.getElementsByTagName('input')[0];
input.click(); // browser simulated click
specs(() => describe('clicked', function () {
it('Should display clicked state message', function () {
let p=document.getElementsByTagName('p')[0];
return (p.innerText==='Clicked!')
});
}))
},1000) // the timeout could be 0 for faster test execution, but 1000 millisecond gives you a change to see that the click takes place
return comp;
});