无法检查 expect(elm).not.toBeVisible() 的语义-ui 反应组件

Cannot check expect(elm).not.toBeVisible() for semantic-ui react component

我正在尝试测试一个 React 组件并使用 expect(elm).not.toBeVisible() 但没有成功。

更新 3

我已将代码简化为这种更简单的形式:

// ./TestItem.js
import React from 'react'
import './TestItem.css'

export default ({ hide }) => {
  return <div className={hide ? 'shouldHide' : ''}>Text</div>
}

// ./__tests__/TestItem.test.js
import React from 'react'
import { render } from 'react-testing-library'
import TestItem from '../TestItem'
import 'jest-dom/extend-expect'
import 'react-testing-library/cleanup-after-each'


test.only('TestItem should render correctly', async () => {
  const { getByText, debug } = render(<TestItem hide={true} />)
  const itemNode = getByText('Text')
  debug()
  expect(itemNode).not.toBeVisible()
})

// ./TestItem.css
.shouldHide {
  display: none;
}

测试结果:

 TestItem should render correctly

    expect(element).not.toBeVisible()

    Received element is visible:
      <div class="shouldHide" />

       7 |   const itemNode = getByText('Text')
       8 |   debug()
    >  9 |   expect(itemNode).not.toBeVisible()
         |                        ^
      10 | })
      11 |

debug() 日志:

console.log node_modules/react-testing-library/dist/index.js:58
    <body>
      <div>
        <div
          class="shouldHide"
        >
          Text
        </div>
      </div>
    </body>

更新二:

好吧,这变得很奇怪,因为我通过了测试 codesanbox,但在我的本地机器上仍然没有成功。


我原来的问题:

我使用 React、semantic-ui-react 和 react-testing-library。

代码如下:

// ComboItem.test.js    
import React from 'react'
import ComboItem from '../ComboItem'
import { render } from 'react-testing-library'
import comboXoi from '../images/combo-xoi.jpg'
import 'path/to/semantic/semantic.min.css'

describe('ComboItem', () => {
  test('should render', async () => {
    const { getByText, debug } = render(
      <ComboItem image={comboXoi} outOfStock={false} />
    )
    const outOfStockNotice = getByText('Out of stock')
    debug()
    expect(outOfStockNotice).not.toBeVisible()
  })
})

// ComboItem.js
import React from 'react'
import { Card, Image } from 'semantic-ui-react'

export default ({ image, outOfStock = false }) => {
  return (
    <Card>
      <Image
        src={image}
        dimmer={{
          active: outOfStock,
          inverted: true,
          'data-testid': 'combo-item-dimmer',
          content: (
            <span style={{ marginTop: 'auto', color: 'black' }}>
               Out of stock
            </span>
          ),
        }}
      />
    </Card>
  )
}

我得到的是这里的结果:

ComboItem › should render

    expect(element).not.toBeVisible()

    Received element is visible:
      <span style="margin-top: auto; color: black;" />

      at Object.test (src/app/screens/App/screens/SaleEntries/screens/CreateSaleEntry/screens/StickyRiceComboSelect/__tests__/ComboItem.test.js:14:34)
      at process._tickCallback (internal/process/next_tick.js:68:7)

我试过在浏览器上查看组件渲染结果,测试代码中的节点 outOfStockNotice 实际上是隐藏的,因为它的父节点是 div 和 class dimmer 具有 display: none.

风格

根据 jest-dom 文档(由 testing-react-library 使用:

toBeVisible

An element is visible if all the following conditions are met:

  • it does not have its css property display set to none
  • it does not have its css property visibility set to either hidden or collapse
  • it does not have its css property opacity set to 0
  • its parent element is also visible (and so on up to the top of the DOM tree)

请帮忙。我真的不知道这里会出什么问题。

更新:

我在这里包含 debug() 的结果:

console.log node_modules/react-testing-library/dist/index.js:58
      <body>
        <div>
          <div
            class="ui card"
          >
            <div
              class="ui image"
            >
              <div
                class="ui inverted dimmer"
                data-testid="combo-item-dimmer"
              >
                <div
                  class="content"
                >
                  <span
                    style="margin-top: auto; color: black;"
                  >
                    Out of stock
                  </span>
                </div>
              </div>
              <img
                src="combo-xoi.jpg"
              />
            </div>
          </div>
        </div>
      </body>

根据 react-testing-library 作者本人的说法the answer

Probably a JSDOM limitation (in codesandbox it runs in the real browser). Actually, the problem is that the css isn't actually loaded into the document in JSDOM. If it were, then that would work. If you can come up with a custom jest transform that could insert the css file into the document during tests, then you'd be set.

So this would work if you were using CSS-in-JS.

所以基本上测试中的 import './TestItem.css' 部分将不起作用,因为 JSDOM 不加载它,因此 jest-dom 无法理解 class shouldHide 的意思 display: none.

更新:

根据这个Stack Overflow thread,可以将css插入jsdom:

import React from 'react'
import { render } from 'react-testing-library'
import TestItem from '../TestItem'

import fs from 'fs'
import path from 'path'

test.only('TestItem should render correctly', async () => {
  const cssFile = fs.readFileSync(
    path.resolve(__dirname, '../TestItem.css'),
    'utf8'
  )
  const { container, getByText, debug } = render(<TestItem hide={true} />)

  const style = document.createElement('style')
  style.type = 'text/css'
  style.innerHTML = cssFile
  container.append(style)

  const itemNode = getByText('Text')
  debug()
  expect(itemNode).not.toBeVisible()
})

然后测试应该会通过。