/**
 * TEAM: frontend_infra
 * @flow strict
 */
/* eslint-disable flexport/jsx-must-contain-jsx */

import * as React from "react";
import {render, screen} from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import Dropdown from "../Dropdown";
import Button from "../button/Button";

function mountDropdown(props: ?$Shape<React.ElementConfig<typeof Dropdown>>) {
  return render(
    <Dropdown parent="" {...props}>
      {props?.children ?? ""}
    </Dropdown>
  );
}

describe("Dropdown", () => {
  it("renders given parent properly", () => {
    const buttonText = "Click me for dropdown";
    const result = mountDropdown({
      parent: <Button>{buttonText}</Button>,
    });

    expect(result.getByText(buttonText) != null).toBe(true);
  });

  it("selecting the button opens a dropdown with given children", () => {
    const buttonText = "Click me for dropdown";
    const content = "foobar";
    const result = mountDropdown({
      parent: <Button>{buttonText}</Button>,
      children: content,
    });
    const button = result.getByText(buttonText);

    userEvent.click(button);

    expect(screen.getByText(content) != null).toBe(true);
  });

  it("onOpen and onClose work", async () => {
    const buttonText = "Click me for dropdown";
    const content = "foobar";
    const onOpen = jest.fn();
    const onClose = jest.fn();
    const result = mountDropdown({
      parent: <Button>{buttonText}</Button>,
      children: content,
      onOpen,
      onClose,
    });
    const button = result.getByText(buttonText);

    userEvent.click(button);

    expect(onOpen.mock.calls.length).toBe(1);
    expect(onClose.mock.calls.length).toBe(0);

    userEvent.click(button);

    expect(onOpen.mock.calls.length).toBe(1);
    expect(onClose.mock.calls.length).toBe(1);

    userEvent.click(button);

    expect(onOpen.mock.calls.length).toBe(2);
    expect(onClose.mock.calls.length).toBe(1);

    userEvent.click(button);

    expect(onOpen.mock.calls.length).toBe(2);
    expect(onClose.mock.calls.length).toBe(2);
  });

  it("onKeyDown work", async () => {
    const buttonText = "Click me for dropdown";
    const content = "foobar";
    const onKeyDown = jest.fn();
    const result = mountDropdown({
      parent: <Button>{buttonText}</Button>,
      children: content,
      onKeyDown,
    });
    const button = result.getByText(buttonText);

    userEvent.click(button);

    userEvent.keyboard("a");

    expect(onKeyDown.mock.calls.length).toBe(1);

    userEvent.keyboard("b");

    expect(onKeyDown.mock.calls.length).toBe(2);

    userEvent.keyboard("cde");

    expect(onKeyDown.mock.calls.length).toBe(5);

    userEvent.keyboard("{Up}");

    expect(onKeyDown.mock.calls.length).toBe(6);
  });
});
