You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Enzyme测试react-truncate的展开收起功能

Testing Expand/Collapse Interaction for react-truncate-based ReadMore Component with Enzyme

I've run into this exact issue before with react-truncate and Enzyme shallow rendering! The problem is that shallow rendering doesn't render the internal elements of the Truncate component, so your "Read more" link is hidden inside the ellipsis prop of Truncate and not directly accessible via shallow queries. Here's how to fix this and implement your full test flow:

Why Your Initial Approach Failed

When you use shallow(), Enzyme only renders your ReadMore component and stops at the Truncate component—it doesn't dive into Truncate's internal JSX. That's why your debug output only shows the Truncate element, and calling wrapper.toggleLines() returns undefined (you need to access the component instance first, but even then, you still need to trigger the click through the actual UI element or prop).

Solution 1: Use Full Rendering with mount()

The most straightforward way is to use mount() instead of shallow() to render the entire component tree, including the Truncate component's internal elements. This lets you directly query for the "Read more" and "Show less" links.

Here's the complete test code:

import React from 'react';
import { mount } from 'enzyme';
import ReadMore from './ReadMore';

describe('ReadMore Component', () => {
  const longText = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.';

  it('should initialize with expanded state as false', () => {
    const wrapper = mount(<ReadMore>{longText}</ReadMore>);
    expect(wrapper.state('expanded')).toBe(false);
  });

  it('should set expanded to true when "Read more" is clicked', () => {
    const wrapper = mount(<ReadMore>{longText}</ReadMore>);
    // Find the "Read more" link and simulate click
    const readMoreLink = wrapper.find('a').filterWhere(node => node.text() === 'Read more');
    readMoreLink.simulate('click', { preventDefault: () => {} });
    expect(wrapper.state('expanded')).toBe(true);
  });

  it('should set expanded back to false when "Show less" is clicked', () => {
    const wrapper = mount(<ReadMore>{longText}</ReadMore>);
    // First expand the component
    const readMoreLink = wrapper.find('a').filterWhere(node => node.text() === 'Read more');
    readMoreLink.simulate('click', { preventDefault: () => {} });
    
    // Now find and click "Show less"
    const showLessLink = wrapper.find('a').filterWhere(node => node.text() === 'Show less');
    showLessLink.simulate('click', { preventDefault: () => {} });
    expect(wrapper.state('expanded')).toBe(false);
  });
});

Solution 2: Use Shallow Rendering with Prop Access

If you prefer to keep using shallow() (for faster tests), you can access the ellipsis prop passed to Truncate, which contains your "Read more" link. You can then extract the onClick handler from that prop and trigger it directly:

import React from 'react';
import { shallow } from 'enzyme';
import ReadMore from './ReadMore';
import Truncate from 'react-truncate';

describe('ReadMore Component (Shallow)', () => {
  const longText = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.';

  it('should initialize with expanded state as false', () => {
    const wrapper = shallow(<ReadMore>{longText}</ReadMore>);
    expect(wrapper.state('expanded')).toBe(false);
  });

  it('should set expanded to true when "Read more" is triggered', () => {
    const wrapper = shallow(<ReadMore>{longText}</ReadMore>);
    // Get the Truncate component from the shallow render
    const truncateComponent = wrapper.find(Truncate);
    // Extract the ellipsis prop, which is your span with the "Read more" link
    const ellipsisElement = truncateComponent.prop('ellipsis');
    // Trigger the onClick handler of the link (pass a mock event)
    ellipsisElement.props.children.props.onClick({ preventDefault: () => {} });
    expect(wrapper.state('expanded')).toBe(true);
  });

  it('should set expanded back to false when "Show less" is triggered', () => {
    const wrapper = shallow(<ReadMore>{longText}</ReadMore>);
    // First expand the component
    const truncateComponent = wrapper.find(Truncate);
    const ellipsisElement = truncateComponent.prop('ellipsis');
    ellipsisElement.props.children.props.onClick({ preventDefault: () => {} });
    expect(wrapper.state('expanded')).toBe(true);

    // Now trigger the "Show less" link
    const showLessElement = wrapper.findWhere(node => node.prop('children') === 'Show less');
    showLessElement.props().onClick({ preventDefault: () => {} });
    expect(wrapper.state('expanded')).toBe(false);
  });
});

Key Notes

  • When simulating clicks, always pass a mock event object with preventDefault()—your toggleLines method calls event.preventDefault(), so omitting this will throw an error.
  • For the "Show less" link in shallow rendering, you can use findWhere() to locate the element by its child text, since it's rendered directly in your ReadMore component's JSX.

内容的提问来源于stack exchange,提问作者user988544

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:10:37