Jest / React测试库:是否可以像赛普拉斯一样监视并等待GraphQL查询?

时间:2020-05-10 03:27:10

标签: reactjs graphql cypress apollo-client react-testing-library

我的大部分测试经验是与赛普拉斯在一起的。我正在尝试使用React测试库(此后称为“ RTL”)测试一些React组件。我想知道我是否可以应用与赛普拉斯一起使用的某些技术。

我的(网络)应用程序中有一个部分,显示数据库的搜索结果表。搜索API在GraphQL中实现。我们在前端使用Apollo。可以针对<FilterCheckbox/>组件对搜索进行过滤。它包括四个复选框和一个“全部清除”按钮。复选框状态存储在Apollo缓存中。

我正在为此组件编写规格。我希望测试默认情况下是否选中了前两个复选框,然后单击“清除过滤器”将其全部取消选中。我有以下内容:

import React from 'react'
import FilterCheckboxes from './FilterCheckboxes'
import { render, fireEvent } from 'Utils/test-utils'

import {
  getByText,
  getByTestId
} from '@testing-library/dom'

const props = {
  options: [
    { label: 'new', value: 'FRESH' },
    { label: 'active', value: 'ACTIVE' },
    { label: 'closed', value: 'CLOSED' },
    { label: 'removed', value: 'ARCHIVED' },
  ],
  statusArray: [
    'FRESH',
    'ACTIVE',
  ],
  cacheKey: 'status',
}

describe('FilterCheckboxes component', () => {
  const { container } = render(<FilterCheckboxes {...props} />)

  const checkNew = getByTestId(container,'checkbox_new')
    .querySelector('input[type="checkbox"]')

  const checkActive = getByTestId(container, 'checkbox_active')
    .querySelector('input[type="checkbox"]')

  const checkClosed = getByTestId(container,'checkbox_closed' )
    .querySelector('input[type="checkbox"]')

  const checkRemoved = getByTestId(container, 'checkbox_removed')
    .querySelector('input[type="checkbox"]')

  const clearButton = getByText(container, 'clear status filters')


  it('should render the checkboxes with the correct default state', () => {
    expect(checkNew).toHaveProperty('checked', true)
    expect(checkActive).toHaveProperty('checked', true)
    expect(checkClosed).toHaveProperty('checked', false)
    expect(checkRemoved).toHaveProperty('checked', false)
  })

  it('Should clear all checkboxes when clear filters is clicked', () => {
    fireEvent.click(clearButton)
    setTimeout(() => {
      expect(checkNew).toHaveProperty('checked', false)
      expect(checkActive).toHaveProperty('checked', false)
      expect(checkClosed).toHaveProperty('checked', false)
      expect(checkRemoved).toHaveProperty('checked', false)
    }, 500)
  })
})

测试通过了,但是第二个测试只有在我执行500ms的任意延迟时才通过。如果没有它,则在expect()调用时,复选框仍处于默认状态。

如果这是赛普拉斯测试,并且onClick称为REST API,我将执行以下操作:

cy.server()
cy.route('POST', '/foo/bar/v2', '@someAliasedFixture').as('fooBar')

cy.get('.my-button')
.click()
.then(() => {
    cy.wait('@fooBar')
    // continue test here as we know that the call completed
})

是否可以通过Jest / RTL / GraphQL / Apollo做类似的事情?

更新: 今天早上又看了一眼。看来waitFor()是打算在异步方案中使用的函数。但是,如果我这样做

it('should deselect checkboxes when Clear Filters is clicked', async () => {
  fireEvent.click(clearButton)
  waitFor(expect(checkNew).toHaveProperty('checked', false))
})

它只是失败,因为仍选中该复选框。当然可以使用RTL进行测试吗?

根据我看过的示例,正​​统方法似乎是将点击处理程序函数作为道具传递,expect() .toHaveBeenCalled()被调用。

对吗?对我来说这似乎是错误的。我的组件不是使onClick处理程序响应单击事件而触发的原因。 React.js实现了这一目标。单击foo()时检查是否调用<MyComponent onClick={foo}/>并不能测试 my 代码是否有效。它正在测试React.js是否有效。

已解决! 感谢@flo:

  it('should render the checkboxes with the correct default state', () => {
    expect(checkNew).toBeChecked()
    expect(checkActive).toBeChecked()
    expect(checkClosed).not.toBeChecked()
    expect(checkRemoved).not.toBeChecked()
  })

  it('should deselect checkboxes when Clear Filters is clicked', async () => {
    fireEvent.click(clearButton)
    waitFor(() => {
      expect(checkNew).not.toBeChecked()
      expect(checkActive).not.toBeChecked()
      expect(checkClosed).not.toBeChecked()
      expect(checkRemoved).not.toBeChecked()
    })
  })

1 个答案:

答案 0 :(得分:3)

我同意,您应该像真实用户一样进行测试,因此,您绝对应该测试复选框处于正确状态,而不是测试单击处理程序是否被调用。这就是促进反应测试库的原因。

您确定吗?

expect(checkNew).toHaveProperty('checked', false);

我从没有使用过它,但是在阅读文档时,我不确定这是否可以完成工作(https://jestjs.io/docs/en/expect#tohavepropertykeypath-value)。实际上,我不知道它如何工作。

您考虑使用https://github.com/testing-library/jest-dom,尤其是使用https://github.com/testing-library/jest-dom#tobechecked吗?

相关问题