import React from "react";
import "@testing-library/jest-dom/extend-expect";
import { render, RenderResult, fireEvent } from "@testing-library/react";
import { Search, SearchResultHeader, SearchResultItem } from "../../";

const DEBOUNCE_WAIT_INTERVAL = 1000;

let elementRender: RenderResult;
let onChange: jest.Mock;
let onItemClick: jest.Mock;

jest.useFakeTimers();

beforeEach(() => {
  onChange = jest.fn();
  onItemClick = jest.fn();
  elementRender = render(
    <Search
      ariaLabel="Products Search"
      className="custom-class"
      debounce={DEBOUNCE_WAIT_INTERVAL}
      onChange={onChange}
      placeholder="Search by keyword"
      size="sm"
      value="defaultValue"
    >
      <SearchResultHeader>Recent</SearchResultHeader>
      <SearchResultItem href="path-to">Repository</SearchResultItem>
      <SearchResultItem onClick={onItemClick}>John Wick</SearchResultItem>
    </Search>
  );
});

afterEach(() => {
  onChange.mockReset();
  onItemClick.mockReset();
  elementRender.unmount();
});

test("should show Search and Search Results", () => {
  const { queryByTestId } = elementRender;
  expect(queryByTestId("honey-ui-search")).toBeTruthy();
  expect(queryByTestId("honey-ui-search-result-items")).toBeTruthy();
});

test("Search should have default classNames and pass custom classNames", () => {
  const { queryByTestId } = elementRender;
  expect(queryByTestId("honey-ui-search")).toHaveClass("input-group custom-class input-group-sm");
});

test("Search should default value, placeholder and aria-label", () => {
  const { queryByTestId, getByPlaceholderText, getByLabelText } = elementRender;
  expect(queryByTestId("honey-ui-search-input")).toHaveValue("defaultValue");
  expect(getByPlaceholderText("Search by keyword")).toBeTruthy();
  expect(getByLabelText("Products Search")).toBeTruthy();
});

test("Search Result should be displayed", () => {
  const { getByText } = elementRender;
  expect(getByText("Recent")).toBeTruthy();
  expect(getByText("Repository")).toBeTruthy();
  expect(getByText("John Wick")).toBeTruthy();
});

test("should have URL  on Search Result Item", () => {
  const { getByText } = elementRender;
  expect(getByText("Repository").closest("a")).toHaveAttribute("href", "path-to");
});

test("should call onItemClick when click on Search Result Item", () => {
  const { getByText } = elementRender;
  fireEvent.click(getByText("John Wick"));

  expect(onItemClick).toHaveBeenCalled();
});

test(`should call onChange after ${DEBOUNCE_WAIT_INTERVAL} ms`, () => {
  setTimeout(() => onChange && onChange(), DEBOUNCE_WAIT_INTERVAL);

  expect(onChange).not.toBeCalled();

  jest.advanceTimersByTime(DEBOUNCE_WAIT_INTERVAL);

  expect(onChange).toBeCalled();
  expect(onChange).toBeCalledTimes(1);
});
