使用带有表单输入元素的 ReactBootstrap 模式对 React 组件进行单元测试

Posted

技术标签:

【中文标题】使用带有表单输入元素的 ReactBootstrap 模式对 React 组件进行单元测试【英文标题】:Unit Testing React Component using ReactBootstrap Modal with a Form Input element 【发布时间】:2021-08-30 16:52:55 【问题描述】:

我有 react-bootstrap 的 Modal 组件,它有一个输入,当我对 Focus 进行单元测试时,它说它收到了整个文档,而不仅仅是 Input 元素。

有谁知道为什么焦点转到整个文档(Modal 是否使整个文档集中)。非常感谢您的帮助。下面是我的代码

Signup.js

import  Container, Form, Modal  from 'react-bootstrap';

const Signup = () => 
const handleClick = (e) => 
  e.preventDefault();
  const element = e.currentTarget;
  const id = element.getAttribute('id');
  if (id === 'userEmail') 
    const emailLabel = document.getElementById('emailLabel');
    emailLabel.style.fontSize = '30px';
  
;
return (
  <Container>
    <Modal show=true autoFocus>
      <Modal.Header>Header</Modal.Header>
      <Modal.Body>
        <Form>
          <Form.Group>
            <Form.Label>
              <span id="emailLabel">Email</span>
              <Form.Control
                name="userEmail"
                id="userEmail"
                data-testid="userEmail"
                type="email"
                onClick=(e) => handleClick(e)
              />
            </Form.Label>
          </Form.Group>
        </Form>
      </Modal.Body>
    </Modal>
  </Container>
);
;
export default Signup;

Signup.test.js

import Signup from '.';

describe('helo', () => 
it('signup', async () => 
 render(<Signup />);
 const emailInput = screen.getByTestId('userEmail');
 fireEvent.click(emailInput);
 expect(emailInput).toHaveFocus();
);
);

结果


    Expected element with focus:
      <input class="form-control" data-testid="userEmail" id="userEmail" name="userEmail" type="email" />
    Received element with focus:
      <div aria-modal="true" class="fade modal show" role="dialog" style="display: block;" tabindex="-1"><div class="modal-dialog"><div class="modal-content"><div class="modal-header">Header</div><div class="modal-body"><form class=""><div class="form-group"><label class="form-label"><span id="emailLabel" style="font-size: 30px;">Email</span><input class="form-control" data-testid="userEmail" id="userEmail" name="userEmail" type="email" /></label></div></form></div></div></div></div>

      123 |     const emailInput = screen.getByTestId('userEmail');
      124 |     fireEvent.click(emailInput);
    > 125 |     expect(emailInput).toHaveFocus();
          |                        ^
      126 |   );
      127 | );
      128 |

【问题讨论】:

【参考方案1】:

首先,在我看来,您如何导入 Signup 组件这行代码很奇怪:import Signup from '.';

但我也认为您应该传递 render(&lt;Signup show=true/&gt;); 以呈现模式并能够聚焦输入,因为只有浏览器上的可见元素是可聚焦的

【讨论】:

【参考方案2】:

考虑 fireEvent.click,它会创建一个 click 事件并在给定的 DOM 节点上调度该事件。这适用于大多数情况下,您只是想测试单击元素时会发生什么,但是当用户实际单击您的元素时,这些是通常触发的事件(按顺序):

fireEvent.mouseOver(element)
fireEvent.mouseMove(element)
fireEvent.mouseDown(element)
element.focus() (if that element is focusable)
fireEvent.mouseUp(element)
fireEvent.click(element)

看看这篇博文https://testing-library.com/docs/guide-events/

【讨论】:

感谢豪尔赫。当我在触发点击事件之前添加“emailInput.focus()”时,我的代码就像魅力一样工作。

以上是关于使用带有表单输入元素的 ReactBootstrap 模式对 React 组件进行单元测试的主要内容,如果未能解决你的问题,请参考以下文章

将按钮与带有标签的输入表单对齐

使用 jQuery 检查表单是不是有输入元素

带有 display:none 表单元素的 jquery 验证器插件

提交后将焦点设置在输入元素上

带有表单和 Angular 日期的 Angular/HTML 输入本地日期时间

如何从动态元素发布表单