简体   繁体   English

@testing-library/react 测试表单 onSubmit

[英]@testing-library/react test form onSubmit

In a simple scenario like so在这样一个简单的场景中

function onSubmit() { e.preventDefault(); /* Some Submit Logic */ }

<form data-testid="form" onSubmit={(e) => onSubmit(e)}>
   <button type="submit" data-testid="submit-button">Submit</button>
</form>

How do I make sure that the form gets submitted when the submit button is clicked?单击提交按钮时,如何确保表单被提交?

const { queryByTestId } = render(<LoginForm/>);
const LoginForm = queryByTestId("form")
const SubmitButton = queryByTestId("submit-button")
fireEvent.click(SubmitButton)

???

How do I test if onSubmit() has been called or maybe form has been submitted?如何测试是否已调用 onSubmit() 或是否已提交表单?

Basically, here is what I "solved" it:基本上,这就是我“解决”的问题:

// LoginForm.js

export function LoginForm({ handleSubmit }) {

     const [name, setName] = useState('');

     function handleChange(e) {
         setName(e.target.value)
     }

     return (
         <form data-testid="form" onSubmit={() => handleSubmit({ name })}>
              <input required data-testid="input" type="text" value={name} onChange={(e) => handleChange(e)}/>
              <button type="submit" data-testid="submit-button">Submit</button>
         </form>
     )
}

export default function LoginPage() {

    function handleSubmit(e) {
        // submit stuff
    }

    return <LoginForm handleSubmit={(e) => handleSubmit(e)}/>

}

Now the test's file:现在测试的文件:

// LoginForm.test.js

import React from 'react';
import { render, fireEvent } from "@testing-library/react";
import LoginPage, { LoginForm } from "./LoginPage";

it("Form can be submited & input field is modifiable", () => {

    const mockSubmit = jest.fn();
    const { debug, queryByTestId } = render(<LoginForm handleSubmit={mockSubmit}/>);

    fireEvent.change(queryByTestId("input"), { target: { value: 'Joe Doe' } }); // invoke handleChange
    fireEvent.submit(queryByTestId("form"));

    expect(mockSubmit).toHaveBeenCalled(); // Test if handleSubmit has been called 
    expect(mockSubmit.mock.calls).toEqual([[{name: 'Joe Doe'}]]); // Test if handleChange works

});

I'd suggest to use nock to intercept request sending from form and return mocked response after.我建议使用nock拦截从表单发送的请求并在之后返回模拟响应。 For example:例如:

nock('https://foo.bar').post('/sign-up', formValues).reply(201);

But I would like to know a better solutions tho.但我想知道更好的解决方案。

getByRole('form', { name: /formname/i })

RTL is meant to move away from using id's. RTL 旨在远离使用 id。 An ideal solution is to name your form which does two things.一个理想的解决方案是命名您的表单,它会做两件事。 It allow you to uniquely name it making it useful to screen readers and also gets the browser to assign it a role of form.它允许您对其进行唯一命名,使其对屏幕阅读器有用,并让浏览器为其分配表单角色。 Without the name, getByRole('form') will do nothing.如果没有名称, getByRole('form') 将什么也不做。

MDN: <form> element MDN:<form> 元素

Implicit ARIA role - form if the form has an accessible name, otherwise no corresponding role隐式 ARIA 角色 - 如果表单具有可访问的名称,则表单,否则没有相应的角色

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM