0

I'm having trouble trying to test functions declared inside a React component. In my case i have these functions called handleChange and changeCapacity , they're used by the Form.control element, it's a Select.

I wrote a test that should use these Selects, so i thought i was also testing the functions they are associated with, but apparently i'm not since my Coverage file state that the functions are not tested.

This is the Component i'm testing,

const TableFilter: React.FC<TableFilterProps> = ({ handleTables }) => {
  const tables: TableI[] = useSelector(tablesSelector);

  const filteredTables: TableI[] = useSelector(filteredTablesSelector);

  const prevCapacity: number = useSelector(capacitySelector);
  const prevLocation: string = useSelector(locationSelector);

  const dispatch = useDispatch();

  const locations: string[] = tables.map(
    (table: { location: string }) => table.location
  );
  const capacity: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9];

  const uniqueLocations = [...new Set(locations)];

  const handleChange = (event: { target: { value: any } }) => {
    let locationFilter = event.target.value;

    dispatch(storeLocation(locationFilter));

    if (filteredTables && prevCapacity) {
      const available = tables.filter(
        (table: { location: string; capacity: number }) =>
          table.location === locationFilter && table.capacity >= prevCapacity
      );

      available.length === 0
        ? handleTables()
        : dispatch(filterTables(available));
    } else {
      const filteredArr = tables.filter(
        (table: { location: string }) => table.location === locationFilter
      );
      dispatch(filterTables(filteredArr));
    }
  };

  const changeCapacity = (event: { target: { value: any } }) => {
    let capacityFilter = event.target.value;

    dispatch(storeCapacity(capacityFilter));

    if (filteredTables && prevLocation) {
      const available = tables.filter(
        (table: { capacity: number; location: string }) =>
          table.capacity >= capacityFilter && table.location === prevLocation
      );

      available.length === 0
        ? handleTables()
        : dispatch(filterTables(available));
    } else {
      const filteredArr = tables.filter(
        (table: { capacity: number }) => table.capacity >= capacityFilter
      );
      dispatch(filterTables(filteredArr));
    }
  };

  return (
    <Form>
      <Form.Group className="mb-3" controlId="formBasicEmail">
        <Form.Label>Select a table</Form.Label>
        <Form.Control
          onChange={handleChange}
          as="select"
          aria-label="form-select-location"
        >
          <option>Select your table's location</option>
          {uniqueLocations &&
            uniqueLocations.map((location: string, index: number) => (
              <option aria-label="location" key={index} value={location}>
                {location}
              </option>
            ))}
        </Form.Control>
      </Form.Group>

      <Form.Group className="mb-3" controlId="formBasicEmail">
        <Form.Label>Select the capacity of your table</Form.Label>
        <Form.Control
          onChange={changeCapacity}
          as="select"
          aria-label="form-select-capacity"
        >
          <option>Number of persons sitting </option>
          {capacity &&
            capacity.map((capacity: number, index: number) => (
              <option aria-label="capacity" key={index} value={capacity}>
                {capacity}
              </option>
            ))}
        </Form.Control>
      </Form.Group>
    </Form>
  );
};

export default TableFilter;

this is the test i'm running on this Component:

describe("TableFilter", () => {
  const filteredTablesSelectorSpy = jest.spyOn(
    actions,
    "filteredTablesSelector"
  );
  const tablesSelectorSpy = jest.spyOn(actions, "tablesSelector");
  const capacitySelectorSpy = jest.spyOn(actions, "capacitySelector");
  const locationSelectorSpy = jest.spyOn(actions, "locationSelector");

  beforeEach(() => {
    filteredTablesSelectorSpy.mockReset().mockReturnValue([]);
    tablesSelectorSpy.mockReset().mockReturnValue([]);
    capacitySelectorSpy.mockReset().mockReturnValue(0);
    locationSelectorSpy.mockReset().mockReturnValue("");
  });

  test("testing Capacity and Location Selects, should find the Table with the values selected", () => {
    render(<TableFilter handleTables={() => {}} />);

    const capacitySelect = screen.getByLabelText("form-select-capacity");
    const locationSelect = screen.getByLabelText("form-select-location");

    expect(capacitySelect).toBeInTheDocument();
    expect(locationSelect).toBeInTheDocument();

    waitFor(() =>
      user.selectOptions(
        capacitySelect,
        within(capacitySelect).getByRole("option", { name: "8" })
      )
    );

    waitFor(() =>
      user.selectOptions(
        locationSelect,
        within(locationSelect).getByRole("option", { name: "Patio" })
      )
    );

    waitFor(() =>
      expect(screen.getByRole("option", { name: "8" })).toBeInTheDocument()
    );

    waitFor(() =>
      expect(screen.getByRole("option", { name: "Patio" })).toBeInTheDocument()
    );

    waitFor(() => expect(filteredTablesSelectorSpy).toHaveBeenCalledTimes(2));
    waitFor(() => expect(tablesSelectorSpy).toHaveBeenCalledTimes(1));
    waitFor(() => expect(capacitySelectorSpy).toHaveBeenCalledTimes(2));
    waitFor(() => expect(locationSelectorSpy).toHaveBeenCalledTimes(2));
  });
});
  • 2
    For what it is worth, you appear to be misusing/abusing [`aria-label`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-label_attribute) here-- you are using it as a stand-in for a test-id (which itself should be avoided because you should be using accessible matchers). You should properly wire up a label to the input using an `id` on the input and a `for` on the label, and then match by that label text. – Alexander Nied Dec 02 '21 at 05:18
  • Thank you Alexander! I ended up using lots of aria-labels because i was having trouble finding accessible matchers but i'll try to remove themI'd try using the label as you suggested, thanks! – Michelangelo Dec 02 '21 at 10:27
  • Are the handler functions not being covered at all, or are they not being fully covered? Surely testing the ` – juliomalves Dec 05 '21 at 17:27

0 Answers0