我想检查单击按钮后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)


如何测试属性?

最佳答案

通过验证道具来检查属性是可以的。模拟点击就可以了。
测试失败的唯一原因是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

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

另一种方法是使用.dive()这样

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


甚至在初始化时:

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


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

09-16 11:06