import * as React from "react";
import { render, screen, fireEvent, cleanup } from "@testing-library/react";
import ButtonSliderGroup from "./ButtonSliderGroup";

const props = {
  value: 10,
  maxValue: 95,
  minValue: 0,
  onValueChange: (): any => null,
};
const button1 = {
  command: "SHRINK",
  style: { padding: 35 },
  icon: "TestingIcon",
};
const button2 = {
  command: "GROW",
  style: { padding: 25 },
  icon: "ButtonTwoIconTest",
};

const getSliderValue = (container) => {
  return parseInt(container.querySelectorAll("input[type='hidden']")[0].value);
};

describe("<ButtonSliderGroup /> Rendering >", () => {
  afterEach(cleanup);

  it(`Should render component in the dom`, () => {
    render(<ButtonSliderGroup {...props} />);
    expect(screen.getByTestId("ButtonSliderGroup")).not.toBe(null);
  });

  it("Should render a slider if the showSlider prop is set to true", () => {
    render(<ButtonSliderGroup {...props} showSlider />);
    expect(screen.queryByTestId("ButtonSliderGroup-slider")).toBeTruthy();
  });

  it(`Slider should be positioned at the value provided in the prop`, () => {
    const value = 50;

    const { container } = render(
      <ButtonSliderGroup {...props} showSlider value={value} />
    );

    const sliderValue = getSliderValue(container);

    expect(sliderValue).toBe(value);
  });

  it(`Should not show a slider when the showSlider prop is set to false`, () => {
    render(<ButtonSliderGroup {...props} showSlider={false} />);
    expect(screen.queryByTestId("ButtonSliderGroup-slider")).toBe(null);
  });

  it(`Should show a label caption for the group using the label prop`, () => {
    const randomText = Math.random()
      .toString(36)
      .slice(2);
    render(<ButtonSliderGroup {...props} label={randomText} />);
    expect(screen.getByText(randomText)).not.toBe(null);
  });

  it(`Should render a button with the value, style, events, icon attributes provided in the button1 prop`, () => {
    const onValueChange = jest.fn();

    const { debug, getByTestId, queryByText } = render(
      <ButtonSliderGroup
        {...props}
        button1={button1}
        onValueChange={onValueChange}
      />
    );
    fireEvent.click(getByTestId("ButtonSliderGroup-Button1"));

    expect(queryByText(button1.icon)).not.toBe(null);
    expect(onValueChange.mock.calls[0][0]).toBe(button1.command);
    expect(getByTestId("ButtonSliderGroup-Button1").getAttribute("style")).toBe(
      `padding: ${button1.style.padding}px;`
    );
  });

  it(`Should render a button with the value, style, events, icon attributes provided in the button2 prop`, () => {
    const onValueChange = jest.fn();

    render(
      <ButtonSliderGroup
        {...props}
        button2={button2}
        onValueChange={onValueChange}
        // onValueChange={(value) => document.write(value)}
      />
    );
    fireEvent.click(screen.getByTestId("ButtonSliderGroup-Button2"));

    expect(screen.queryByText(button2.icon)).not.toBe(null);
    expect(onValueChange.mock.calls[0][0]).toBe(button2.command);
    expect(
      screen.getByTestId("ButtonSliderGroup-Button2").getAttribute("style")
    ).toBe(`padding: ${button2.style.padding}px;`);
  });

  it(`Should not allow any values below the provided minValue prop`, () => {
    const { container } = render(
      <ButtonSliderGroup {...props} showSlider value={63} maxValue={44} />
    );
    expect(getSliderValue(container)).toBe(44);
  });

  it(`Should not allow any values above the provided maxValue prop`, () => {
    const { container } = render(
      <ButtonSliderGroup {...props} showSlider value={63} minValue={75} />
    );
    expect(getSliderValue(container)).toBe(75);
  });
});

describe("<ButtonSliderGroup /> Events >", () => {
  afterEach(cleanup);

  it(`Should trigger the onValueChange() event with the new value when either of the buttons are clicked`, () => {
    const onValueChange = jest.fn();
    // render the component
    const { container, debug } = render(
      <ButtonSliderGroup
        {...props}
        showSlider
        button1={button1}
        onValueChange={onValueChange}
      />
    );

    // click one of the buttons
    fireEvent.click(screen.getByTestId("ButtonSliderGroup-Button1"));

    // confirm that the onValueChange event was fired and the value was passed
    expect(onValueChange.mock.calls[0][0]).toBe(button1.command);
  });

  it(`Should trigger the onValueChange() event with the new value when the slider is moved`, () => {
    const value = 66;
    const onValueChange = jest.fn();
    // render the component
    const { container, debug } = render(
      <ButtonSliderGroup
        {...props}
        showSlider
        __testSliderValue={value}
        onValueChange={onValueChange}
      />
    );

    // change the slider position
    fireEvent.click(screen.getByTestId("__testSliderValueUpdate"));
    // console.log(onValueChange.mock.calls);

    // confirm that the onValueChange event was fired and the value was passed
    expect(onValueChange.mock.calls[0][1]).toBe(value);
  });
});

describe("<ButtonSliderGroup /> Hooks >", () => {
  afterEach(cleanup);
  test.skip(`Should trigger the _onButtonSliderGroupRender_ plugin hook when the ButtonSliderGroup component renders`, () => {});

  test.skip(`Should trigger the _onButtonSliderGroupChange_ plugin hook when the value of the ButtonSliderGroup property changes`, () => {});

  test.skip(`Should trigger the onButtonSliderGroupFinish plugin hook when the mouse button is released (on the button or slider)`, () => {});
});
