失败测试(testing-library/react):无法找到包含文本的元素:
Failing test (testing-library/react): Unable to find an element with the text:
我正在尝试使用 testing-library/react 的 react-select (rc-select) 组件编写一些测试。测试现在是 运行,但下拉列表如下所示:
我也在控制台中收到警告:
react-dom.development.js:21 Warning: Encountered two children with the same key,
空.
测试 运行 的变化来自
<Option key={option.key || option} value={option.key || option}>
{option.name || option}
</Option>```
到
<Option key={option.value} value={option.value}>
{option.label}
</Option>
代码使用testing-library/react:
Select测试组件:
import React from "react";
import Select from "../../packages/lab/src/select/Select.jsx";
const ReactSelectTestComponent = (props) => {
const { options } = props;
const onChange = (event) => {
if (props.onChange) {
props.onChange(event);
}
};
return (
<div data-testid="my-select-component">
<Select
className="basic-single"
classNamePrefix="select"
name="myOptions"
placeholder="Select an option"
options={options}
onChange={onChange} />
</div>
);
};
export default ReactSelectTestComponent;
Select.test.js:
import React from "react";
import { render, fireEvent, cleanup, waitFor } from '@testing-library/react';
import SelectTestComponent from "./SelectTestComponent";
it('should call onChange when the first option is selected', async () => {
const mockedOptions = [
{ label: 'Mocked option 1', value: 'mocked-option-1' },
{ label: 'Mocked option 2', value: 'mocked-option-2' },
{ label: 'Mocked option 3', value: 'mocked-option-3' },
{ label: 'Mocked option 4', value: 'mocked-option-4' },
{ label: 'Mocked option 5', value: 'mocked-option-5' },
{ label: 'Mocked option 6', value: 'mocked-option-6' },
{ label: 'Mocked option 7', value: 'mocked-option-7' },
{ label: 'Mocked option 8', value: 'mocked-option-8' },
{ label: 'Mocked option 9', value: 'mocked-option-9' },
{ label: 'Mocked option 10', value: 'mocked-option-10' },
];
const mockedOnChange = jest.fn();
const { getByText, queryByTestId } = render(<SelectTestComponent
options={mockedOptions}
onChange={mockedOnChange} />);
const mySelectComponent = queryByTestId('my-select-component');
expect(mySelectComponent).toBeDefined();
expect(mySelectComponent).not.toBeNull();
// We trigger the right element to show autocomplete
const input = mySelectComponent.getElementsByTagName('input')[0];
fireEvent.keyDown(input, { key: 'ArrowDown' });
// Leave as is
await waitFor(() => getByText('Mocked option 1')[0]);
fireEvent.click(getByText('Mocked option 1')[0]);
expect(mockedOnChange).toHaveBeenCalledTimes(1);
// Another change is to only selected value instead of entire option
expect(mockedOnChange).toHaveBeenCalledWith('mocked-option-1');
})
错误:
Select分量:
/* eslint-disable react/forbid-prop-types */
import React from "react";
import PropTypes from "prop-types";
import styled from "styled-components";
import RcSelect, { Option } from "rc-select";
import { Icon } from "@opt-ui/core";
import { colors } from "@opt-ui/styles";
import { GlobalStyle } from "./Select.styles";
const ArrowContainer = styled.div`
position: relative;
top: 2px;
`;
const BaseSelect = styled(RcSelect).attrs(() => { })`
font-family: Equinor;
`;
// Component
const Select = React.forwardRef((props, ref) => {
const { className, options, value, menuItemSelectedIcon, ...other } = props;
return (
<>
<GlobalStyle />
<BaseSelect
ref={ref}
className={className}
value={value}
inputIcon={
<ArrowContainer>
<Icon type="chevron_down" color={colors.grey20} />
</ArrowContainer>
}
menuItemSelectedIcon={menuItemSelectedIcon}
{...other}
>
{options.map((option) => (
<Option key={option.value} value={option.value}>
{option.label}
</Option>
))}
</BaseSelect>
</>
);
});
Select.propTypes = {
options: PropTypes.array.isRequired,
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
menuItemSelectedIcon: PropTypes.element
};
Select.defaultProps = {
value: undefined,
menuItemSelectedIcon: null
};
export default Select;
我检查了您的代码,发现您需要更改一些内容才能使其正常工作。
首先,您可能需要仅更改 Option
渲染 label
并且设置选项的值是按字面设置 value
:
<Option key={option.value} value={option.value}> // key/value as unique key
{option.label} // render only label
</Option>
下一步是通过 keydown 正确触发显示自动完成列表到 rc-select
呈现的 input
:
// We trigger the right element to show autocomplete
const input = mySelectComponent.getElementsByTagName('input')[0];
fireEvent.keyDown(input, { key: 'ArrowDown' });
// Leave as is
await waitForElement(() => getByText('Mocked option 1'));
fireEvent.click(getByText('Mocked option 1'));
expect(mockedOnChange).toHaveBeenCalledTimes(1);
// Another change is to only selected value instead of entire option
expect(mockedOnChange).toHaveBeenCalledWith('mocked-option-1');
我正在尝试使用 testing-library/react 的 react-select (rc-select) 组件编写一些测试。测试现在是 运行,但下拉列表如下所示:
我也在控制台中收到警告:
react-dom.development.js:21 Warning: Encountered two children with the same key,
空.
测试 运行 的变化来自
<Option key={option.key || option} value={option.key || option}>
{option.name || option}
</Option>```
到
<Option key={option.value} value={option.value}>
{option.label}
</Option>
代码使用testing-library/react:
Select测试组件:
import React from "react";
import Select from "../../packages/lab/src/select/Select.jsx";
const ReactSelectTestComponent = (props) => {
const { options } = props;
const onChange = (event) => {
if (props.onChange) {
props.onChange(event);
}
};
return (
<div data-testid="my-select-component">
<Select
className="basic-single"
classNamePrefix="select"
name="myOptions"
placeholder="Select an option"
options={options}
onChange={onChange} />
</div>
);
};
export default ReactSelectTestComponent;
Select.test.js:
import React from "react";
import { render, fireEvent, cleanup, waitFor } from '@testing-library/react';
import SelectTestComponent from "./SelectTestComponent";
it('should call onChange when the first option is selected', async () => {
const mockedOptions = [
{ label: 'Mocked option 1', value: 'mocked-option-1' },
{ label: 'Mocked option 2', value: 'mocked-option-2' },
{ label: 'Mocked option 3', value: 'mocked-option-3' },
{ label: 'Mocked option 4', value: 'mocked-option-4' },
{ label: 'Mocked option 5', value: 'mocked-option-5' },
{ label: 'Mocked option 6', value: 'mocked-option-6' },
{ label: 'Mocked option 7', value: 'mocked-option-7' },
{ label: 'Mocked option 8', value: 'mocked-option-8' },
{ label: 'Mocked option 9', value: 'mocked-option-9' },
{ label: 'Mocked option 10', value: 'mocked-option-10' },
];
const mockedOnChange = jest.fn();
const { getByText, queryByTestId } = render(<SelectTestComponent
options={mockedOptions}
onChange={mockedOnChange} />);
const mySelectComponent = queryByTestId('my-select-component');
expect(mySelectComponent).toBeDefined();
expect(mySelectComponent).not.toBeNull();
// We trigger the right element to show autocomplete
const input = mySelectComponent.getElementsByTagName('input')[0];
fireEvent.keyDown(input, { key: 'ArrowDown' });
// Leave as is
await waitFor(() => getByText('Mocked option 1')[0]);
fireEvent.click(getByText('Mocked option 1')[0]);
expect(mockedOnChange).toHaveBeenCalledTimes(1);
// Another change is to only selected value instead of entire option
expect(mockedOnChange).toHaveBeenCalledWith('mocked-option-1');
})
错误:
Select分量:
/* eslint-disable react/forbid-prop-types */
import React from "react";
import PropTypes from "prop-types";
import styled from "styled-components";
import RcSelect, { Option } from "rc-select";
import { Icon } from "@opt-ui/core";
import { colors } from "@opt-ui/styles";
import { GlobalStyle } from "./Select.styles";
const ArrowContainer = styled.div`
position: relative;
top: 2px;
`;
const BaseSelect = styled(RcSelect).attrs(() => { })`
font-family: Equinor;
`;
// Component
const Select = React.forwardRef((props, ref) => {
const { className, options, value, menuItemSelectedIcon, ...other } = props;
return (
<>
<GlobalStyle />
<BaseSelect
ref={ref}
className={className}
value={value}
inputIcon={
<ArrowContainer>
<Icon type="chevron_down" color={colors.grey20} />
</ArrowContainer>
}
menuItemSelectedIcon={menuItemSelectedIcon}
{...other}
>
{options.map((option) => (
<Option key={option.value} value={option.value}>
{option.label}
</Option>
))}
</BaseSelect>
</>
);
});
Select.propTypes = {
options: PropTypes.array.isRequired,
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
menuItemSelectedIcon: PropTypes.element
};
Select.defaultProps = {
value: undefined,
menuItemSelectedIcon: null
};
export default Select;
我检查了您的代码,发现您需要更改一些内容才能使其正常工作。
首先,您可能需要仅更改 Option
渲染 label
并且设置选项的值是按字面设置 value
:
<Option key={option.value} value={option.value}> // key/value as unique key
{option.label} // render only label
</Option>
下一步是通过 keydown 正确触发显示自动完成列表到 rc-select
呈现的 input
:
// We trigger the right element to show autocomplete
const input = mySelectComponent.getElementsByTagName('input')[0];
fireEvent.keyDown(input, { key: 'ArrowDown' });
// Leave as is
await waitForElement(() => getByText('Mocked option 1'));
fireEvent.click(getByText('Mocked option 1'));
expect(mockedOnChange).toHaveBeenCalledTimes(1);
// Another change is to only selected value instead of entire option
expect(mockedOnChange).toHaveBeenCalledWith('mocked-option-1');