javascript 使用Jest和react-testing-library测试具有大量输入字段的表单的正确方法是什么?

6l7fqoea  于 2023-09-29  发布在  Java
关注(0)|答案(2)|浏览(113)

我有一个有很多输入的表单,问题是,有没有一种方法可以简化所有这些单个输入变量的处理,因为它们的列表看起来很难看。对具有两个输入的表单的测试看起来干净而优雅,但是这个表单看起来像是我做错了什么。还有一个'specialties'数据变量,我不认为它属于mocks文件夹,因为它不是一个模拟的API调用,只是表单的一个 prop 。在tests文件夹中,是否有一个约定,即我应该把这些变量放在什么位置?我会很感激任何其他反馈我做错了什么,谢谢。

import React from 'react'
import { Provider } from 'react-redux'
import { render, screen } from '@testing-library/react'
import store from '../../../store'
import PupilForm from '../../../components/forms/PupilForm'
import specialties from '../../../__mocks__/specialties.json'

const mockHandleFormData = jest.fn()
const mockOpenInfoModal = jest.fn()

describe('<PupilForm /> component', () => {
    // eslint-disable-next-line
    let view
    // inputs
    let nameInput
    let specialtyInput
    let genderInput
    let birthDateInput
    let mainSchoolClassInput
    let benefitsInput
    let mainSchoolInput
    let homeAddressInput
    let phoneNumberInput
    let applicantNameInput
    let contactEmailInput
    let fathersNameInput
    let fathersPhoneInput
    let fathersEmploymentInfoInput
    let mothersNameInput
    let mothersPhoneInput
    let mothersEmploymentInfoInput
    // checkboxes
    let docsCheck
    let processDataCheck
    let paymentObligationsCheck
    // buttons
    let submitButton
    let resetButton

    beforeEach(() => {
        view = render(
            <Provider store={store}>
                <PupilForm
                    handleFormData={mockHandleFormData}
                    openInfoModal={mockOpenInfoModal}
                    specialties={specialties.map(spec => spec.title)}
                    mode="public"
                />
            </Provider>
        )

        nameInput = screen.getByRole('textbox', { name: /Прізвище та повне ім'я учня/ })
        specialtyInput = screen.getByRole('combobox', { name: /Фах/ })
        genderInput = screen.getByRole('combobox', { name: /Стать/ })
        birthDateInput = screen.getByLabelText(/Дата народження/)
        mainSchoolClassInput = screen.getByRole('combobox', { name: /Клас ЗОШ/ })
        benefitsInput = screen.getByRole('combobox', { name: /Пільги %/ })
        mainSchoolInput = screen.getByRole('textbox', { name: /В якому закладі навчается/ })
        homeAddressInput = screen.getByRole('textbox', { name: /Домашня адреса/ })
        phoneNumberInput = screen.getByRole('textbox', { name: /Телефонний номер учня/ })
        applicantNameInput = screen.getByRole('textbox', { name: /Ім'я особи, яка звертається із заявою/ })
        contactEmailInput = screen.getByRole('textbox', { name: /Контактна електронна пошта/ })

        fathersNameInput = screen.getByRole('textbox', { name: /Ім'я батька/ })
        fathersPhoneInput = screen.getByRole('textbox', { name: /Телефонний номер батька/ })
        fathersEmploymentInfoInput = screen.getByRole('textbox', { name: /Місце роботи батька/ })

        mothersNameInput = screen.getByRole('textbox', { name: /Ім'я матері/ })
        mothersPhoneInput = screen.getByRole('textbox', { name: /Телефонний номер матері/ })
        mothersEmploymentInfoInput = screen.getByRole('textbox', { name: /Місце роботи матері/ })

        docsCheck = screen.getByRole('checkbox', { name: /Я зобов'язаний надати ці документи/ })
        processDataCheck = screen.getByRole('checkbox', { name: /Я згоден на збір та обробку/ })
        paymentObligationsCheck = screen.getByRole('checkbox', { name: /Зобов'язання про оплату/ })

        submitButton = screen.getByRole('button', { name: /Відправити/ })
        resetButton = screen.getByRole('button', { name: /Очистити/ })
    })

    it('in renders all fields correctly', () => {
        expect(/Дані\/інформація про учня/).toBeInTheDocument
        expect(nameInput).toHaveAttribute('type', 'text')
        expect(specialtyInput).toHaveClass('custom-select')
        expect(genderInput).toHaveClass('custom-select')
        expect(birthDateInput).toHaveAttribute('type', 'date')
        expect(mainSchoolClassInput).toHaveClass('custom-select')
        expect(benefitsInput).toHaveClass('custom-select')
        expect(mainSchoolInput).toHaveAttribute('type', 'text')
        expect(homeAddressInput).toHaveAttribute('type', 'text')
        expect(phoneNumberInput).toHaveAttribute('type', 'text')
        expect(applicantNameInput).toHaveAttribute('type', 'text')
        expect(contactEmailInput).toHaveAttribute('type', 'email')

        expect(/Дані\/інформація о батьках/).toBeInTheDocument
        expect(fathersNameInput).toHaveAttribute('type', 'text')
        expect(fathersPhoneInput).toHaveAttribute('type', 'text')
        expect(fathersEmploymentInfoInput).toHaveAttribute('type', 'text')
        expect(mothersNameInput).toHaveAttribute('type', 'text')
        expect(mothersPhoneInput).toHaveAttribute('type', 'text')
        expect(mothersEmploymentInfoInput).toHaveAttribute('type', 'text')

        expect(docsCheck).toHaveAttribute('type', 'checkbox')
        expect(processDataCheck).toHaveAttribute('type', 'checkbox')
        expect(paymentObligationsCheck).toHaveAttribute('type', 'checkbox')

        expect(submitButton).toHaveAttribute('type', 'submit')
        expect(resetButton).toHaveAttribute('type', 'reset')
    })

    /*
    it('some other test that uses the same inputs', () => {
        // expect all inputs to be able to change their values on user input
    })
    */
})
bejyjqdl

bejyjqdl1#

有没有一种方法可以简化所有这些单一输入变量的处理?
我不这么认为.我个人会去掉所有的字段变量,只通过screen访问它们。但做你觉得对的事。
您也可以尝试缩短一些查询。因为你使用的是正则表达式,所以你不需要指定整个元素name
但这个看起来我做错了什么
测试看起来很好。我想指出的是,你可能不需要测试某些东西,比如expect(nameInput).toHaveAttribute('type', 'text'),因为你已经可以免费使用nameInput = screen.getByRole('textbox', { name: /Прізвище та повне ім'я учня/ })了。
你也会在上面使用像userEvent.type这样的东西,所以我认为它已经足够安全了。
还有一个'specialties'数据变量,我不认为它属于mocks文件夹,因为它不是一个模拟的API调用,只是一个表单的 prop
mocks文件夹下放置测试数据也没有任何问题,即使它没有模拟API调用。
如果您认为在语义上更合适的话,也许可以将文件夹命名为fixtures。或者您可以将其保存在将使用它的测试文件中。这似乎是一种代码风格偏好,每个人都会对此有不同的看法。
在tests文件夹中,是否有一个约定,即我应该把这些变量放在什么位置?
__mocks__fixturesdata,你能想到的。我建议你四处移动,直到感觉合适,然后与团队成员协商。
This question非常相似

wnavrhmk

wnavrhmk2#

我正在做的项目有很多表单和很多字段。我不得不模拟填充和提交,我使用了类似的概念。
另外,请记住getByRole非常慢。确保使用testId或getByText来查找是否可能。但是,我们有一个解决方案,设置hidden:真

const fields = 
[
    {name: 'Product Name', role: 'textbox'},
    {name: 'Allowed Countries', role: 'combobox'},
    {name: 'Enable Ecom', role: 'checkbox'}
    ...
]

test('All fields render correctly', () => {
    render <ProductForm />

    // If sync then forEach if async then map, reduce, or for..of
    fields.forEach(field => {
        const namePattern = new RegExp(`^${field.name}$`, 'i')
        const inputEl = screen.getByRole(field.role, {name: namePattern, hidden: true})
        expect(inputEl).toBeInTheDocument()
    })
})

相关问题