Search code examples
reactjsreact-testing-librarytruncation

react-testing-library: Verify text truncation


I have a component "Label" which has rudimentary truncation support:

import "./styles.css";
export default function Label(props) {
  const className = props.truncate ? "truncate" : "";
  return <label className={className}>{props.children}</label>;
}

The truncate css class:

.truncate {
  display: inline-block;
  overflow: hidden;
  white-space: pre;
  text-overflow: ellipsis;
  display: inline-flex;
  min-width: 0;
  max-width: 100%;
}

Here is a codesandbox which demonstrates the component and it's truncation prop:

screenshot of codesandbox output


Now I'm at the point where I want to add some test coverage for the truncation feature. I'm using react-testing-library, but I'm not sure the best way to assert that the end of the text is not visible with truncation.

Here is my attempt:

const longText = 'START Lorem ipsum dolor sit amet, consectetur adipiscing elit. In ac commodo massa END';
describe('Label', () => {
  it('displays long text', () => {
    render(<Label>{longText}</Label>);
    expect(screen.getByText(/^START/)).toBeInTheDocument(); // pass
    expect(screen.getByText(/END$/)).toBeInTheDocument(); // pass
  });
  it('displays long text with truncation', () => {
    render(<Label truncate={true}>{longText}</Label>);
    expect(screen.getByText(/^START/)).toBeInTheDocument(); // pass
    expect(screen.queryByText(/END$/)).not.toBeVisible(); // FAILURE
  });
});

The last expect is failing with:

Received element is visible:
    <label class="truncate" />

I understand that I could test for the presence of the class name, but our team feels that it's a poor practice to rely on that.

Is there a best-practice way to test for text truncation?


Solution

  • If you add a screen.debug right after the render with truncate, like this:

    render(<Label truncate={true}>{longText}</Label>);
    
    screen.debug();
    

    the output will be:

    <label class="truncate">
          START Lorem ipsum dolor sit amet, consectetur adipiscing elit. In ac commodo massa END
    </label>
    

    As you can see the entire text is rendered and what makes the text visible/not visible is the css overflow property.

    Said that, I think the best approach here its just verify if the component has or hasn't the overflow property:

    expect(screen.getByText(/^START/)).toHaveStyle("overflow: hidden");