2

I'm trying to write a test and can't work out why my hover isn't working. The full code is here. I have a recharts chart element, which renders, is responsive, and shows a tooltip containing the expected data (here, amino acid name and ratio of total provided sequence, eg: 'A: 0.06') on hover over any bar:

import { useStore } from '@nanostores/react';
import { countAminoAcids } from '../../../functions/utilFunctions/countAminoAcids';
import { inputStore } from '../../../stores/input';
import type { InputLabelProps } from '../../../types';
import {
  ResponsiveContainer,
  BarChart,
  Bar,
  CartesianGrid,
  XAxis,
  YAxis,
  Tooltip,
} from 'recharts';
import { CountAminoAcidsTooltip } from './CountAminoAcidsTooltip';

export default function CountAminoAcids({
  ariaLabelContent,
}: InputLabelProps) {
  const sanitisedInputFromStore = useStore(inputStore);
  const resiCounts = countAminoAcids(sanitisedInputFromStore);
  const resiCountsArray = Object.entries(resiCounts).map(
    ([key, value]) => {
      // add the key to the value
      return { ...value, key };
    }
  );

  // remove total from resiCountsArray
  const individualResiCountsArray = resiCountsArray.slice(0, -1);
  return (
    <ResponsiveContainer aria-label={ariaLabelContent}>
      <BarChart
        className="proteinBar"
        data={individualResiCountsArray}
      >
        <CartesianGrid strokeDasharray="3 3" />
        <YAxis
          dataKey="ratio"
          tick={{ fill: 'hsl(42, 100%, 50%)' }}
        />
        <XAxis dataKey="key" tick={{ fill: 'hsl(42, 100%, 50%)' }} />
        <Bar dataKey="ratio" fill="hsl(42, 100%, 50%)" />
        <Tooltip
          wrapperStyle={{
            outline: 'none',
          }}
          content={<CountAminoAcidsTooltip />}
        />
      </BarChart>
    </ResponsiveContainer>
  );
}

I have tests passing for the error message I've encoded when an invalid protein sequence is entered, and for the Y Axis rendering the expected values when a known protein is input. I also have a sample tooltip test from freecodecamp working perfectly, so I know I have react testing library and userEvent.hover working correctly. However, mine always fails. I patterned my test on this post. I think I have the correct document.querySelectorAll as I get the expected NodeList of 20 items when I run in Chrome's console. Where am I going wrong??

// protParams.test.tsx
// MPKCPKCNKEVYFAERVTSLGKDWHRPCLKCEKCGKTLTSGGHAEHEGKPYCNHPCYAAMFGPKGFGRGGAESHTFK

import { describe, test, expect, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
// import modules to test
import { Molecule } from '../../src/types';
import Input from '../../src/components/react/Input';
import CountAminoAcids from '../../src/components/react/protein/CountAminoAcids';
import ProteinParameters from '../../src/components/react/protein/ProteinParameters';
import type { ResponsiveContainerProps } from 'recharts';

vi.mock('recharts', async () => {
  const mockRecharts = await vi.importActual<any>('recharts');
  return {
    ...mockRecharts,
    ResponsiveContainer: ({ children }: ResponsiveContainerProps) => (
      <mockRecharts.ResponsiveContainer width={800} height={800}>
        {children}
      </mockRecharts.ResponsiveContainer>
    ),
  };
});

describe('test amino acid counting', () => {
  const user = userEvent.setup();
  let inputBox: HTMLElement;
  // reset input after each test
  beforeEach(() => {
    render(
      <Input
        ariaLabelContent={'DNA input form for Protein parameters'}
        placeholderText={'Enter DNA sequence here...'}
        inputType={Molecule.Protein}
      />
    );
    inputBox = screen.getByLabelText(
      'DNA input form for Protein parameters'
    );
  });

  // two passing tests omitted

  test('test tooltip on hover', async () => {
    // define input
    const dna =
      'MPKCPKCNKEVYFAERVTSLGKDWHRPCLKCEKCGKTLTSGGHAEHEGKPYCNHPCYAAMFGPKGFGRGGAESHTFK';

    // enter DNA into input box
    await user.type(inputBox, dna);
    expect(inputBox).toHaveValue(dna);
    // render output
    render(<CountAminoAcids ariaLabelContent={'Amino acid count'} />);


    const bars = document.querySelectorAll('.recharts-layer.recharts-bar-rectangle');

    // expected output
    await userEvent.hover(bars[0]);

    // test
    expect(screen.getByText('A: 0.06'));
  });
});

I have tried a different selector for bars (const bars = document.querySelectorAll('.recharts-bar-rectangle');) with the same result

1 Answers1

1

Try changing the last line in your test to:

expect(await screen.findByText('A: 0.06'))

As the appearance of the tooltip is an asynchronous event you need your test to wait for it to appear (findBy functions are a combination of getBy queries and waitFor, see here).

Ben Smith
  • 19,589
  • 6
  • 65
  • 93
  • good spot, thanks. I also realised my querySelector _is_ wrong, and should be `const bars = document.querySelectorAll('.recharts-rectangle');`. I also, also added a call to `screen.logTestingPlaygroundURL();` and I don't think the bars are rendering on the chart, so the test is right and there is no tooltip to find (it only appears on bars with data). The chart works fine in both dev and build, so I assume its a mocking issue – Chris Cozens Mar 17 '23 at 10:34