/**
 * TEAM: frontend_infra
 * @flow
 */

// TODO: Fix this eslint issue on next edit. This is an autogenerated comment.
// eslint-disable-next-line flexport/no-legacy-dependencies
import {mount, ReactWrapper} from "enzyme";
import SearchableMultiselectFilter from "../SearchableMultiselectFilter";

// Popper uses document.createRange, which JSDOM doesn't support
jest.mock("popper.js");

type SearchableMultiselectFilterOptions = $ReadOnlyArray<{
  +value: string,
  +label: string,
  ...
}>;

const testOptions = [
  {
    value: "green-house",
    label: "Green House",
  },
  {
    value: "blue-house",
    label: "Blue House",
  },
  {
    value: "red-house",
    label: "Red House",
  },
  {
    value: "green-car",
    label: "Green Car",
  },
  {
    value: "blue-car",
    label: "Blue Car",
  },
  {
    value: "red-car",
    label: "Red Car",
  },
];

function mountSearchableMultiSelectFilter(
  propOverrides: {+onChange: ($ReadOnlyArray<any>) => void, ...},
  options: SearchableMultiselectFilterOptions
) {
  // $FlowFixMe[cannot-spread-inexact] upgrade 0.121.1 -> 0.122.0
  const props = {
    label: "test",
    value: [],
    onChange: () => {},
    options,
    ...propOverrides,
  };

  return mount(<SearchableMultiselectFilter {...props} />);
}

function openFilter(filter: ReactWrapper<typeof SearchableMultiselectFilter>) {
  filter.find("FilterButton").simulate("click");
}

describe("SearchableMultiselectFilter with 3 or fewer options", () => {
  const threeOptions = testOptions.slice(0, 3);

  it("can select a value", () => {
    const handleChange = jest.fn();
    const wrapper = mountSearchableMultiSelectFilter(
      {
        onChange: handleChange,
      },
      threeOptions
    );

    openFilter(wrapper);
    // since there's only 3 options, there is no 'select all' and the first checkbox
    // is for the first option
    const firstOption = wrapper.find("input[type='checkbox']").at(0);
    firstOption.simulate("change");

    expect(handleChange).toHaveBeenCalledWith(["green-house"]);
  });

  it("can search and then select a value", () => {
    const handleChange = jest.fn();
    const wrapper = mountSearchableMultiSelectFilter(
      {
        onChange: handleChange,
      },
      threeOptions
    );

    openFilter(wrapper);

    const input = wrapper.find("MultiInput").find("input");
    input.simulate("change", {target: {value: "red"}});

    // since there's only 3 options, there is no 'select all' and the first checkbox
    // is for the first option
    const firstOption = wrapper.find("input[type='checkbox']").at(0);
    firstOption.simulate("change");

    expect(handleChange).toHaveBeenCalledWith(["red-house"]);
  });
});

describe("SearchableMultiselectFilter with more than 3 options", () => {
  it("can select all", () => {
    const handleChange = jest.fn();
    const wrapper = mountSearchableMultiSelectFilter(
      {
        onChange: handleChange,
      },
      testOptions
    );

    openFilter(wrapper);
    const firstOption = wrapper.find("input[type='checkbox']").at(0);
    firstOption.simulate("change");

    expect(handleChange).toHaveBeenCalledWith([
      "green-house",
      "blue-house",
      "red-house",
      "green-car",
      "blue-car",
      "red-car",
    ]);
  });

  it("can search and then select all results", () => {
    const handleChange = jest.fn();
    const wrapper = mountSearchableMultiSelectFilter(
      {
        onChange: handleChange,
      },
      testOptions
    );

    openFilter(wrapper);

    const input = wrapper.find("MultiInput").find("input");
    input.simulate("change", {target: {value: "red"}});

    const firstOption = wrapper.find("input[type='checkbox']").at(0);
    firstOption.simulate("change");

    expect(handleChange).toHaveBeenCalledWith(["red-house", "red-car"]);
  });
});
