无法为语义 UI 反应组件检查 expect(elm).not.toBeVisible()

Posted

技术标签:

【中文标题】无法为语义 UI 反应组件检查 expect(elm).not.toBeVisible()【英文标题】:Cannot check expect(elm).not.toBeVisible() for semantic-ui react component 【发布时间】:2019-03-19 16:36:36 【问题描述】:

我正在尝试测试一个反应组件并使用 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>

更新 2:

好吧,这变得很奇怪,因为我在 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实际上是隐藏的,因为它的父级是dimmer类的div,具有display: none的样式。

根据jest-domdoc(testing-react-library使用:

可见

如果满足以下所有条件,则元素可见:

它的 css 属性 display 没有设置为 none 它没有将其 css 属性可见性设置为隐藏或折叠 它的 css 属性 opacity 没有设置为 0 它的父元素也是可见的(依此类推直到 DOM 树的顶部)

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

更新:

我在这里包含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>

【问题讨论】:

我认为你不应该这样做await getByText。我认为这是一个同步功能。请把debug()的结果也贴一下好吗? @Gpx 我不认为它真正重要的是同步。他使用 await 并且它以相同的方式适用于异步和同步 @Gpx 你好,我已经更新了我的问题以包含debug() 结果。是的,你是对的,我一定是弄错了它的用法。但是在删除await 之后,我仍然得到同样的错误。请检查我更新的问题。谢谢。 调光器肯定没有激活。缺少“活动”课程。我猜 testing-react-library 的渲染与语义 UI 不同步。如果可能,请尝试等待元素不可见github.com/kentcdodds/react-testing-library#wait @EduardJacko 感谢您的评论爱德华!我试过await wait(() =&gt; expect(outOfStockNotice).not.toBeVisible()),但结果是一样的。我已经用 codesanbox 示例更新了这个问题。它适用于代码沙盒,但不适用于我的机器。任何想法为什么或如何解决这个问题? 【参考方案1】:

这里是the answer根据react-testing-library的作者本人所说:

可能是 JSDOM 限制(在代码和框中,它在真实浏览器中运行)。实际上,问题在于css实际上并未加载到JSDOM中的文档中。如果是这样,那将起作用。如果你能想出一个自定义的 jest 转换,可以在测试期间将 css 文件插入到文档中,那么你已经准备好了。

因此,如果您使用 CSS-in-JS,这将起作用。

所以基本上测试中的import './TestItem.css'部分将不起作用,因为JSDOM不会加载它,因此jest-dom无法理解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()
)

然后测试应该通过了。

【讨论】:

以上是关于无法为语义 UI 反应组件检查 expect(elm).not.toBeVisible()的主要内容,如果未能解决你的问题,请参考以下文章

无法在反应 js 类组件中编辑 datetimepicker material-ui

表格行下的可扩展区域(语义 UI 反应)

反应原生如何检查组件当前是不是显示在屏幕中

警告:道具 `className` 不匹配。当使用带有语义-ui-react 的样式化组件时

在反应中使用字体真棒样式

反应错误 - 检查`t`的渲染方法