javascript - 使用 Jest/Enzyme 检查咏叹调

标签 javascript reactjs unit-testing jestjs enzyme

我想检查单击按钮后 aria-expanded 是否发生变化。这是我的组件

import React, { useState, useRef } from 'react';
import styled from 'styled-components';
import { ArrowTemplate } from './ArrowTemplate';
import { colors } from '../../utils/css';
import { Text } from '../Text';

const Accordion = ({
  rtl, content, color, title, className,
}) => {
  const element = useRef(null);
  const [isAccordionExpanded, setIsAccordionExpanded] = useState(false);
  const toggleAccordion = () => {
    setIsAccordionExpanded(!isAccordionExpanded);
  };
  const height = element.current ? element.current.scrollHeight : '0';
  return (
    <div className={`accordion-section ${className}`}>
      <button className={'accordion-btn'} onClick={toggleAccordion}>
        <p className={'accordion-title'}>
          <Text isRtl={rtl}>{title}</Text>
        </p>
        <ArrowTemplate
          direction={isAccordionExpanded ? 'up' : 'down'}
          onClick={toggleAccordion}
          rtl={rtl}
          color={color}
        />
      </button>
      <AccordionContent
        className={'accordion-content'}
        height={height}
        isAccordionExpanded={isAccordionExpanded}
        ref={element}
        aria-expanded={isAccordionExpanded}
      >
        <div className={'accordion-text'}>
          <Text isRtl={rtl}>{content}</Text>
        </div>
      </AccordionContent>
    </div>
  );
};

export const StyledAccordion = styled(Accordion)`
    font-family: "Open Sans", sans-serif;
    text-align: ${({ rtl }) => (rtl ? 'right' : 'left')};        
    display: flex;
    flex-direction: column;
      .accordion-btn {
        position: relative;
        width: 100%;
        background-color: ${colors.LG_GREY_4};
        color: ${colors.LG_GREY_5};
        cursor: pointer;
        padding: 40px 18px;
        display: flex;
        align-items: center;
        border: none;
        outline: none;
        :hover,
        :focus,
        :active {
          background-color: ${colors.LG_GREY_6};
        }
        .accordion-title {
          ${({ rtl }) => (rtl ? 'right: 50px;' : 'left: 50px;')};
          position: absolute;
          font-weight: 600;
          font-size: 14px;
        }
      }
  `;

export const AccordionContent = styled.div`
        max-height: ${({ isAccordionExpanded, height }) => (isAccordionExpanded ? height : '0')}px;
        overflow: hidden;
        background: ${colors.LG_GREY_7};
        transition: max-height 0.7s;
        .accordion-text {
          font-weight: 400;
          font-size: 14px;
          padding: 18px;
        }
  `;

这是我的测试

import React from 'react';
import { shallow, configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import { StyledAccordion, AccordionContent } from '../Accordion';

configure({ adapter: new Adapter() });

describe('<StyledAccordion/>',
  () => {
    let wrapper;
    beforeEach(() => {
      wrapper = shallow(<StyledAccordion/>);
    });
    it('should match the snapshot', () => {
      expect(wrapper).toMatchSnapshot();
    });
    it('should originally have aria-expanded set to false', () => {
      expect(wrapper.find(AccordionContent).props()['aria-expanded']).toBe(false);
    });
    it('should set aria-expanded to true onClick', () => {
      wrapper.find('.accordion-btn').simulate('click');
      expect(wrapper.find(AccordionContent).props()['aria-expanded']).toBe(true);
    });
  });

这是我在控制台中得到的内容

 FAIL  src/components/Accordion/test/Accordion.test.js (21.497s)
  ● <StyledAccordion/> › should originally have aria-expanded set to false

    Method “props” is meant to be run on 1 node. 0 found instead.

      16 |     });
      17 |     it('should originally have aria-expanded set to false', () => {
    > 18 |       expect(wrapper.find(AccordionContent).props()['aria-expanded']).toBe(false);
         |                                             ^
      19 |     });
      20 |     it('should set aria-expanded to true onClick', () => {
      21 |       wrapper.find('.accordion-btn').simulate('click');

      at ShallowWrapper.single (node_modules/enzyme/src/ShallowWrapper.js:1636:13)
      at ShallowWrapper.single [as props] (node_modules/enzyme/src/ShallowWrapper.js:1160:17)
      at Object.props (src/components/Accordion/test/Accordion.test.js:18:45)

  ● <StyledAccordion/> › should set aria-expanded to true onClick

    Method “simulate” is meant to be run on 1 node. 0 found instead.

      19 |     });
      20 |     it('should set aria-expanded to true onClick', () => {
    > 21 |       wrapper.find('.accordion-btn').simulate('click');
         |                                      ^
      22 |       expect(wrapper.find(AccordionContent).props()['aria-expanded']).toBe(true);
      23 |     });
      24 |   });

      at ShallowWrapper.single (node_modules/enzyme/src/ShallowWrapper.js:1636:13)
      at ShallowWrapper.single [as simulate] (node_modules/enzyme/src/ShallowWrapper.js:1118:17)
      at Object.simulate (src/components/Accordion/test/Accordion.test.js:21:38)

如何测试属性?

最佳答案

通过验证 props 来检查属性是可以的。模拟点击就可以了。 测试失败的唯一原因是 shallow()在幕后工作。

您可以通过检查 wrapper.debug() 自行找出答案返回(例如添加 console.log(wrapper.debug()) )

您会看到类似 <StyledComponentConsumer><Component ...></StyledComponentConsumer> 的内容。所以原因是shallow()不渲染嵌套组件。比如说,如果没有styled-components你试图 shallow(<Accordion />).find('span') (假设 <Text> 应呈现为 <span> )您也永远不会发现这一点。

第一个解决方案可能正在使用mount()而不是shallow() (您甚至不需要更改测试)。但我想走不同的路(不过只是一个意见:https://hackernoon.com/why-i-always-use-shallow-rendering-a3a50da60942)

了解更多关于shallow vs mount的信息差异在https://medium.com/@Yohanna/difference-between-enzymes-rendering-methods-f82108f49084

另一种方法是使用 .dive() 喜欢

wrapper.dive().find(...)

甚至在初始化时:

const wrapper = shallow(...).dive();

最后您可以导出两个版本:基础版本(并针对该版本编写测试)并包装到 styled-components 中。主题化。需要对代码进行更多更改。并且每次添加更多 HOC 包装器时,不喜欢上述测试的方法都不需要更新(例如将组件包装到 styled-components ,然后连接到 redux ,最后添加 withRouter - 测试仍然会以这种方式工作)。但从另一方面来看,这种方法不会测试您的组件,因为它实际上是集成的,所以我不确定这种方法是否更好。

关于javascript - 使用 Jest/Enzyme 检查咏叹调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57774316/

相关文章:

javascript - 如何在 watch 模式下进行任何 mocha 测试之前运行全局设置脚本

c# - TestContext.Properties 可用吗?

javascript - typescript 无法读取未定义的属性 'addEventListener'

javascript - 如何在表中搜索两个年龄之间

javascript - 如何在同一页面中打开网址,也可以使用javascript在新选项卡中打开

javascript - 如何使用 JavaScript 从 HTML 表格的特定单元格中获取值

javascript - React — 使用样式化组件传递 props

javascript - 如果使用多个导入而不是一个命名导入,是否会有性能成本

javascript - 如何让选择器在 React 中处理问答游戏?

c# - Rhino 在 stub IEnumerable<T> 接口(interface)时模拟 : Issue with IEnumerator. MoveNext()