import { render } from "@testing-library/react";

import { DatePicker } from "../DatePicker";

describe("rendering DatePicker", () => {
  describe("initial state", () => {
    it("div wrapper has class 'datepicker control-group'", () => {
      const { container } = render(<DatePicker />);
      expect(
        container.querySelector("div.datepicker.control-group"),
      ).toBeInTheDocument();
    });
    it("input field has class 'form-group__item text-input'", () => {
      const { container } = render(<DatePicker />);
      expect(
        container.querySelector("input.form-group__item.text-input"),
      ).toBeInTheDocument();
    });
    it("calendar button has class 'form-group__item btn btn--square'", () => {
      const { container } = render(<DatePicker />);
      expect(
        container.querySelector("button.form-group__item.btn.btn--square"),
      ).toBeInTheDocument();
    });
    it("calendar button icon has class 'icon icon--medium'", () => {
      const { container } = render(<DatePicker />);
      expect(
        container
          .querySelector("button.form-group__item.btn.btn--square")
          .querySelector("svg"),
      ).toHaveClass("icon icon--medium");
    });
    it("calendar button has class 'form-group__item btn btn--square'", () => {
      const { container } = render(<DatePicker />);
      expect(
        container.querySelector("button.form-group__item.btn.btn--square"),
      ).toBeInTheDocument();
    });
    it("calendar button has aria-expanded set to false", () => {
      const { container } = render(<DatePicker />);
      expect(
        container
          .querySelector("button.form-group__item.btn.btn--square")
          .getAttribute("aria-expanded"),
      ).toBe("false");
    });
    it("calendar button has aria-expanded set to false", () => {
      const { container } = render(<DatePicker />);
      expect(
        container
          .querySelector("button.form-group__item.btn.btn--square")
          .getAttribute("aria-expanded"),
      ).toBe("false");
    });
    it("div dialog wrapper has class 'daypickr'", () => {
      const { container } = render(<DatePicker />);
      expect(container.querySelector('div[role="dialog"]')).toHaveClass(
        "daypickr",
      );
    });
    it("div dialog wrapper has hidden attribute", () => {
      const { container } = render(<DatePicker />);
      expect(container.querySelector('div[role="dialog"]')).toHaveAttribute(
        "hidden",
      );
    });
    it('div dialog wrapper has child with class "daypickr__content"', () => {
      const { container } = render(<DatePicker />);
      expect(
        container.querySelector('div[role="dialog"]').firstChild,
      ).toHaveClass("daypickr__content");
    });
    it('div with class "daypickr__content" has child with class "daypcker__header"', () => {
      const { container } = render(<DatePicker />);
      expect(
        container
          .querySelector("div.daypickr__content")
          .querySelector("div.daypickr__header"),
      ).toBeInTheDocument();
    });
    it('div with class "daypickr__header" has first child with class "daypickr__year-month-wrapper"', () => {
      const { container } = render(<DatePicker />);
      expect(
        container.querySelector("div.daypickr__header").firstChild,
      ).toHaveClass("daypickr__year-month-wrapper");
    });
    it('div with class "daypickr__header" has last child with class "daypickr__pagination"', () => {
      const { container } = render(<DatePicker />);
      expect(
        container.querySelector("div.daypickr__header").lastChild,
      ).toHaveClass("daypickr__pagination");
    });
    it('div with class "daypickr__pagination" has first button child with class "daypickr__button--pagination-prev btn btn--ghost btn--square btn--small"', () => {
      const { container } = render(<DatePicker />);
      expect(
        container.querySelector("div.daypickr__pagination").firstChild,
      ).toHaveClass(
        "daypickr__button--pagination-prev btn btn--ghost btn--square btn--small",
      );
    });
    it('div with class "daypickr__pagination" has last button child with class "daypickr__button--pagination-next btn btn--ghost btn--square btn--small"', () => {
      const { container } = render(<DatePicker />);
      expect(
        container.querySelector("div.daypickr__pagination").lastChild,
      ).toHaveClass(
        "daypickr__button--pagination-next btn btn--ghost btn--square btn--small",
      );
    });
    it('div with class "daypickr__content" has table with class "daypickr__calendar" as child', () => {
      const { container } = render(<DatePicker />);
      expect(
        container
          .querySelector("div.daypickr__content")
          .querySelector("table.daypickr__calendar"),
      ).toBeInTheDocument();
    });
    it('div with class "daypickr__content" has table with class "daypickr__calendar" as child', () => {
      const { container } = render(<DatePicker />);
      expect(
        container
          .querySelector("div.daypickr__content")
          .querySelector("table.daypickr__calendar"),
      ).toBeInTheDocument();
    });
    it('table header has row with class "daypickr__calendar-header-row"', () => {
      const { container } = render(<DatePicker />);
      expect(
        container
          .querySelector("table.daypickr__calendar")
          .querySelector("tr.daypickr__calendar-header-row"),
      ).toBeInTheDocument();
    });
    it('cells in table header have class "daypickr__calendar-header-cell"', () => {
      const { container } = render(<DatePicker />);
      const cells = container
        .querySelector("tr.daypickr__calendar-header-row")
        .querySelectorAll("th");
      cells.forEach((cell) =>
        expect(cell).toHaveClass("daypickr__calendar-header-cell"),
      );
    });
    it('table body has rows with class "daypickr__calendar-row"', () => {
      const { container } = render(<DatePicker />);
      const rows = container
        .querySelector("table.daypickr__calendar")
        .querySelector("tbody")
        .querySelectorAll("tr");
      rows.forEach((row) => expect(row).toHaveClass("daypickr__calendar-row"));
    });
    it('cells in table body have class "daypickr__calendar-cell"', () => {
      const { container } = render(<DatePicker />);
      const cells = container
        .querySelector("table.daypickr__calendar")
        .querySelector("tbody")
        .querySelectorAll("td");
      cells.forEach((cell) =>
        expect(cell).toHaveClass("daypickr__calendar-cell"),
      );
    });
    it('cells in table body have button with class "daypickr__day"', () => {
      const { container } = render(<DatePicker />);
      const cells = container
        .querySelector("table.daypickr__calendar")
        .querySelector("tbody")
        .querySelectorAll("td");
      cells.forEach((cell) =>
        expect(cell.querySelector("button.daypickr__day")).toBeInTheDocument(),
      );
    });
    it('button with current date in table cell has additional class "isToday"', () => {
      const { container } = render(<DatePicker />);
      const dayInMonth = new Date().getDate();
      let current;
      const cells = container
        .querySelector("table.daypickr__calendar")
        .querySelector("tbody")
        .querySelectorAll("td");
      for (let cell of cells) {
        if (cell.querySelector("button.daypickr__day.isToday")) {
          current = cell.firstChild;
          break;
        }
      }
      expect(current.lastChild.textContent === dayInMonth.toString()).toBe(
        true,
      );
    });
  });
  describe("passed props", () => {
    it("div wrapper has data-datepicker-id attribute when id prop is passed", () => {
      const { container } = render(<DatePicker id="test" />);
      expect(
        container
          .querySelector("div.datepicker.control-group")
          .getAttribute("data-datepicker-id"),
      ).toBe("test");
    });
    it("div wrapper has data-datepicker-name attribute when name prop is passed", () => {
      const { container } = render(<DatePicker name="test" />);
      expect(
        container
          .querySelector("div.datepicker.control-group")
          .getAttribute("data-datepicker-name"),
      ).toBe("test");
    });
    it("when id prop is passed input has id {id prop}-input", () => {
      const { container } = render(<DatePicker id="test" />);
      expect(
        container.querySelector("input.form-group__item.text-input").id,
      ).toBe("test-input");
    });
    it("when id prop is passed hidden input has id {id prop}-value", () => {
      const { container } = render(<DatePicker id="test" />);
      expect(container.querySelector('input[type="hidden"]').id).toBe(
        "test-value",
      );
    });
    it("when name prop is passed hidden input has name attribute", () => {
      const { container } = render(<DatePicker name="test" />);
      expect(
        container.querySelector('input[type="hidden"]').getAttribute("name"),
      ).toBe("test");
    });
    it("when id prop is passed calendar button has aria-controls attribute {id prop}-dialog", () => {
      const { container } = render(<DatePicker id="test" />);
      expect(
        container
          .querySelector("button.form-group__item.btn.btn--square")
          .getAttribute("aria-controls"),
      ).toBe("test-dialog");
    });
  });
  describe("passed config prop", () => {
    it("element class is changed when corresponding property is passed in dayPickrConfig.classes", () => {
      const { container } = render(
        <DatePicker
          dayPickrConfig={{ classes: { input: "test-input-class" } }}
        />,
      );
      expect(
        container.querySelector("input.test-input-class"),
      ).toBeInTheDocument();
    });
    it("icon class is changed when calendarIcon property is passed in config", () => {
      const { container } = render(
        <DatePicker
          dayPickrConfig={{
            calendarIcon: {
              type: "svg",
              className: "test-icon-class",
            },
          }}
        />,
      );
      expect(
        container
          .querySelector("button.form-group__item.btn.btn--square")
          .querySelector("svg"),
      ).toHaveClass("test-icon-class");
    });
  });
});
