https://github.com/JedWatson/react-select
我想使用React-Select react组件,但我需要添加测试。
我已经尝试了几种与google相关的选项,但似乎没有任何效果。我有下面的代码,但它不会导致更改事件。我已经能够添加一个焦点事件,它增加了'is-focusedsed'类,但是'is-open'类仍然缺失。
我使用过:https://github.com/JedWatson/react-select/blob/master/test/Select-test.js作为参考
我曾尝试仅在输入字段上使用更改事件,但这也没有帮助。我注意到select有一个onInputChange={this.change}
。
测试
import Home from '../../src/components/home';
import { mount } from 'enzyme'
describe('Home', () => {
it("renders home", () => {
const component = mount(<Home/>);
// default class on .Select div
// "Select foobar Select--single is-searchable"
const select = component.find('.Select');
// After focus event
// "Select foobar Select--single is-searchable is-focussed"
// missing is-open
TestUtils.Simulate.focus(select.find('input'));
//this is not working
TestUtils.Simulate.keyDown(select.find('.Select-control'), { keyCode: 40, key: 'ArrowDown' });
TestUtils.Simulate.keyDown(select.find('.Select-control'), { keyCode: 13, key: 'Enter' });
// as per code below I expect the h2 to have the select value in it eg 'feaure'
});
});
正在测试的组件
import React, { Component } from 'react';
import Select from 'react-select';
class Home extends Component {
constructor(props) {
super(props);
this.state = {
message: "Please select option"};
this.change = this.change.bind(this);
}
change(event) {
if(event.value) {
this.setState({message: event.label});
}
}
render () {
const options = [ {label: 'bug', value: 1} , {label: 'feature', value: 2 }, {label: 'documents', value: 3}, {label: 'discussion', value: 4}];
return (
<div className='content xs-full-height'>
<div>
<h2>{this.state.message}</h2>
<Select
name="select"
value={this.state.message}
options={options}
onInputChange={this.change}
onChange={this.change}
/>
</div>
</div>
);
}
}
export default Home;
命令行 要运行测试我做:
>> npm run test
并在package.js中我有这个脚本:
"test": "mocha --compilers js:babel-core/register -w test/browser.js ./new",
测试设置
和browser.js是:
import 'babel-register';
import jsdom from 'jsdom';
const exposedProperties = ['window', 'navigator', 'document'];
global.document = jsdom.jsdom('<!doctype html><html><body></body></html>');
global.window = document.defaultView;
Object.keys(document.defaultView).forEach((property) => {
if (typeof global[property] === 'undefined') {
exposedProperties.push(property);
global[property] = document.defaultView[property];
}
});
global.navigator = {
userAgent: 'node.js'
};
我还尝试使用此处概述的测试方法:https://github.com/StephenGrider/ReduxSimpleStarter
非常感谢任何帮助
答案 0 :(得分:14)
来自https://github.com/JedWatson/react-select/issues/1357
我找到的唯一解决方案是通过按键模拟选择 事件:
wrapper.find('.Select-control').simulate('keyDown', { keyCode: 40 });
// you can use 'input' instead of '.Select-control'
wrapper.find('.Select-control').simulate('keyDown', { keyCode: 13 });
expect(size).to.eql('your first value in the list')
答案 1 :(得分:9)
我已经尝试了上面列出的两个答案,但还是没有运气。
对我有用的是:
添加classNamePrefix
属性-即list
(如其他答案所述):
<Select
classNamePrefix='list'
options={[
{ label: 'one', value: 'one' },
{ label: 'two', value: 'two' }
]}/>
选择下拉菜单并模拟mouseDown =>打开的下拉菜单:
wrapper
.find('.list__dropdown-indicator')
.simulate('mouseDown', {
button: 0
});
期望事情发生,即我正在检查下拉选项的数量
expect(wrapper.find('.list__option').length).toEqual(2);
如果您可以控制要发送的道具,则可以添加menuIsOpen
道具以始终打开菜单(又称列表中的第2步)。
要打开下拉列表,请从下拉列表中选择一个值:
wrapper.find('.list__option').last().simulate('click', null);
然后您可以测试:
expect(wrapper.find('.list__value-container').text()).toEqual('two');
或
expect(wrapper.find('.list__single-value').text()).toEqual('two');
答案 2 :(得分:8)
这是一个经常性的问题。我正在与100%通过测试的人共享我自己的代码,这些测试涵盖了我的源代码的100%。
我的组件看起来像这样
MySelectComponent({ options, onChange }) {
return <div data-testid="my-select-component">
<Select
className="basic-single"
classNamePrefix="select"
name="myOptions"
placeholder="Select an option"
options={options}
onChange={e => onChange(e)}
/>
</div>;
}
我要在Select
的{{1}}上添加包装器的原因是,呈现的options元素将在其上可用,否则我无法检查是否存在文本选项(您将当您看到我的测试时,会更好地理解。)
这是一个live running example,渲染时会显示带有10个选项的选择组件。
我渲染组件。
我搜索要显示的占位符。
我渲染组件。
我检查我的data-testid="my-select-component"
是否尚未被呼叫。
模拟一个mockedOnChange
事件。
单击第一个选项。
我检查是否使用第一个选项标签和值将ArrowDown
调用了1次。
我渲染组件。
我模拟了第一个选项的选择。
我模拟第二个选项的选择。
我模拟了第9个选项的选择。
我用第9个选项包和值检查mockedOnChange
是否被调用3次。
我渲染组件。
我通过输入“选项1”来模拟输入字段上的更改。
我知道,根据我的mockedOnChange
,过滤后的结果将是“模拟选项1”和“模拟选项10”。
我模拟了2个mockedOptions
事件。
我检查是否使用带有正确标签和值的第二个过滤选项调用了ArrowDown
。
mockedOnChange
我希望有帮助。
答案 3 :(得分:2)
要补充Keith所说的话,使用Simulation方法似乎确实是行使功能的唯一方法。但是,当我在解决方案中尝试使用此方法时,该方法无法正常工作-我使用的是Typescript,但不确定该脚本是否有效果,但我发现有必要在模拟时也传递 key 属性事件:
wrapper.find('.Select-control').simulate('keyDown', { key: 'ArrowDown', keyCode: 40 });
wrapper.find('.Select-control').simulate('keyDown', { key: 'Enter', keyCode: 13 });
我还发现,设置 classNamePrefix 属性使进行简单测试变得容易得多,以使我确信组件可以正确响应模拟事件。设置此前缀时,组件的有用部分会用易于访问的类名进行修饰(您可以通过检查google dev工具中的元素来识别这些有用的类名)。一个简单的Jest测试:
it('react-select will respond to events correctly', () => {
const sut = Enzyme.mount(
<Select
classNamePrefix="list"
options={[{ label: 'item 1', value: 1 }]}
/>);
// The intereactive element uses the suffix __control **note there are two underscores**
sut.find('.list__control').first().simulate('keyDown', { key: 'ArrowDown', keyCode: 40 });
sut.find('.list__control').first().simulate('keyDown', { key: 'Enter', keyCode: 13 });
// the selected value uses the suffix __single-value **note there are two underscores**
expect(sut.find('.list__single-value').first().text()).toEqual('item 1');
});
答案 4 :(得分:1)
只需添加,我实际上必须将classNamePrefix
道具添加到Select
组件中,否则我没有得到任何*__control
类来闩锁上。
答案 5 :(得分:0)
如果有人正在使用酶,这对我有用:
wrapper.find('Select').simulate('change', {
target: { name: 'select', value: 1 },
});
其中“选择”是此处定义的属性名称:
<Select
name="select"
...
“值”是所需选项的值。
答案 6 :(得分:0)
使用测试库和v2.0
试图避免使用诸如classNamePrefix
之类的非常具体的东西,或者通过寻找onChange道具或其他东西来侵入组件的工作方式。
const callback = jest.fn();
const { container, getByText} = render(<Select ... onChange={callback} />);
现在,我们基本上假装自己是屏幕阅读器并聚焦,然后按下向下箭头。
fireEvent.focus(container.querySelector('input'));
fireEvent.keyDown(container.querySelector('input'), { key: 'ArrowDown', code: 40 });
现在单击所需的值
fireEvent.click(getByText('Option Two'));
然后断言。
expect(callback).toHaveBeenCalledWith({ value: 'two', label: 'Option Two'});
答案 7 :(得分:0)
对于那些正在使用酶v3.11.0并进行反应选择v3.0.8的人来说,这对我有用
component.find('Select').simulate('keyDown', { key: 'ArrowDown', keyCode: 40 });
这是我的Select
。我正在与redux-form
<Select
{...input}
styles={customStyles}
options={props.options}
formatGroupLabel={formatGroupLabel}
placeholder="Custom Search..."
isSearchable={true}
onBlur={handleBlur}
/>
测试样本
it('should render dropdown on keyDown', () => {
expect(component.find('MenuList').length).toEqual(1);
});
it('should render the correct amount of options', () => {
expect(component.find('Option').length).toEqual(optionsLength);
});
答案 8 :(得分:0)
https://stackoverflow.com/a/57699061/10786373几乎对我有用。我刚刚添加了keyDown事件来打开选择菜单。
it('my test', () => {
const { container } = getShallow();
const elSelector = container.querySelector('.Select-input');
expect(propsComponent.onPageSizeChange).toHaveBeenCalledTimes(0);
// open select menu
fireEvent.keyDown(elSelector, { keyCode: 13 });
// choose next option
fireEvent.keyDown(elSelector, { key: 'ArrowDown', code: 40 });
// send the option
fireEvent.keyDown(elSelector, { keyCode: 13 });
expect(propsComponent.onPageSizeChange).toHaveBeenCalledTimes(1);
});
答案 9 :(得分:0)
wrapper.find(ReactSelectComponent.instance().onChange(...params));
答案 10 :(得分:0)
带有react-testing-library:
=QUERY(importxml('url-address';"//ul[@class='xxxxxxx']");"SELECT * WHERE Col1 CONTAINS 'x' OR Col1 IS NULL";-1)
然后在我的测试中
<Select id='myId' onChange=(list: ReactSelectOption[]) => {
props.changeGroupItem(
{
items: list ? list.map((item) => item.value) : [],
}
);
}
/>
答案 11 :(得分:0)
有一个库,用于模拟react-select元素上的用户事件,供react-testing-library使用。适用于react select 2 +。
https://www.npmjs.com/package/react-select-event
像这样:
const { getByRole, getByLabelText } = render(
<form role="form">
<label htmlFor="food">Food</label>
<Select options={OPTIONS} name="food" inputId="food" isMulti />
</form>
);
expect(getByRole("form")).toHaveFormValues({ food: "" });
await selectEvent.select(getByLabelText("Food"), ["Strawberry", "Mango"]);
expect(getByRole("form")).toHaveFormValues({ food: ["strawberry", "mango"] });
await selectEvent.select(getByLabelText("Food"), "Chocolate");
expect(getByRole("form")).toHaveFormValues({
food: ["strawberry", "mango", "chocolate"],
});
答案 12 :(得分:0)
我在这里尝试了所有解决方案 - 没有任何效果。
我能够用 user-event 库解决这个问题。查看 selectOptions
函数。