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

import { Hero } from "../";

const image = {
  default: "test-img",
  sm: "test-img-sm",
  lg: "test-img-lg",
  xl: "test-img-xl",
  xxl: "test-img-xxl",
};

// title is required
describe("rendering Hero", () => {
  describe("initial state", () => {
    it("has default class hero", () => {
      const { container } = render(<Hero title="test-title" />);
      expect(container.getElementsByClassName("hero").length).toBe(1);
    });
    it("has default class justify-content-space-between", () => {
      const { container } = render(<Hero title="test-title" />);
      expect(
        container.getElementsByClassName("justify-content-space-between")
          .length,
      ).toBe(1);
    });
    it("has default class hero__content", () => {
      const { container } = render(<Hero title="test-title" />);
      expect(container.getElementsByClassName("hero__content").length).toBe(1);
    });
    it("has default class h2", () => {
      const { container } = render(<Hero title="test-title" />);
      expect(container.getElementsByClassName("h2").length).toBe(1);
    });
  });

  describe("passed title and description props", () => {
    it("has class hero__description when description is set", () => {
      const { container } = render(
        <Hero description="test-description" title="test-title" />,
      );
      expect(container.getElementsByClassName("hero__description").length).toBe(
        1,
      );
    });
    it("has class bold when description is set", () => {
      const { container } = render(
        <Hero description="test-description" title="test-title" />,
      );
      expect(container.getElementsByClassName("bold").length).toBe(1);
    });
    it("has class h1 when textSize is set to large", () => {
      const { container } = render(
        <Hero textSize="large" title="test-title" />,
      );
      expect(container.getElementsByClassName("h1").length).toBe(1);
    });
    it("has class large bold when description is set and textSize is set to large", () => {
      const { container } = render(
        <Hero
          description="test-description"
          textSize="large"
          title="test-title"
        />,
      );
      expect(container.getElementsByClassName("large").length).toBe(1);
      expect(container.getElementsByClassName("bold").length).toBe(1);
    });
    it("renders title", () => {
      const { getByText } = render(<Hero title="test-title" />);
      expect(getByText("test-title")).toBeInTheDocument();
    });
    it("renders description", () => {
      const { getByText } = render(
        <Hero description="test-description" title="test-title" />,
      );
      expect(getByText("test-description")).toBeInTheDocument();
    });
  });
  describe("passed price prop", () => {
    it("has classes h2 & hero__price when price is set", () => {
      const { container } = render(
        <Hero price="test-price" title="test-title" />,
      );
      expect(container.getElementsByClassName("h2").length).toBe(2); // title + price
      expect(container.getElementsByClassName("hero__price").length).toBe(1);
    });
    it("renders price when price is string", () => {
      const { getByText } = render(
        <Hero price="test-price" title="test-title" />,
      );
      expect(getByText("test-price")).toBeInTheDocument();
    });
    it("renders price when price is object", () => {
      const { getByText } = render(
        <Hero
          price={{
            amount: 10.99,
            prefix: "test-prefix",
            suffix: "test-suffix",
          }}
          title="test-title"
        />,
      );
      expect(getByText("test-prefix10,99 €test-suffix")).toBeInTheDocument();
    });
  });
  describe("passed button prop", () => {
    it("renders button element when button prop is set", () => {
      const { container } = render(
        <Hero button={{ children: "btn-test" }} title="test-title" />,
      );
      expect(container.getElementsByClassName("btn").length).toBe(1);
    });
    it("button's children are rendered", () => {
      const { getByText } = render(
        <Hero button={{ children: "btn-test" }} title="test-title" />,
      );
      expect(getByText("btn-test")).toBeInTheDocument();
    });
  });
  describe("passed sticker prop", () => {
    it("renders sticker element when sticker prop is set", () => {
      const { container } = render(
        <Hero sticker={{ children: "sticker-test" }} title="test-title" />,
      );
      expect(container.getElementsByClassName("sticker").length).toBe(1);
    });
    it("sticker's children are rendered", () => {
      const { getByText } = render(
        <Hero sticker={{ children: "sticker-test" }} title="test-title" />,
      );
      expect(getByText("sticker-test")).toBeInTheDocument();
    });
    it("sticker has class hero__sticker", () => {
      const { container } = render(
        <Hero sticker={{ children: "sticker-test" }} title="test-title" />,
      );
      expect(container.getElementsByClassName("hero__sticker").length).toBe(1);
    });
    it("sticker has additional class when set in sticker prop", () => {
      const { container } = render(
        <Hero
          sticker={{
            children: "sticker-test",
            className: "sticker-test-class",
          }}
          title="test-title"
        />,
      );
      expect(container.getElementsByClassName("hero__sticker").length).toBe(1);
      expect(
        container.getElementsByClassName("sticker-test-class").length,
      ).toBe(1);
    });
    ["black", "orange"].map((color) => {
      it(`sticker has sticker--${color} class when sticker.color is set to ${color}`, () => {
        const { container } = render(
          <Hero
            sticker={{ children: "btn-test", color: color }}
            title="test-title"
          />,
        );
        expect(
          container.getElementsByClassName(`sticker--${color}`).length,
        ).toBe(1);
      });
    });
  });
  describe("passed image prop", () => {
    it("renders image element when image prop is set", () => {
      const { container } = render(<Hero image={image} title="test-title" />);
      expect(container.getElementsByClassName("img").length).toBe(1);
    });
    it("image has additional class hero__image", () => {
      const { container } = render(<Hero image={image} title="test-title" />);
      expect(container.getElementsByClassName("hero__image").length).toBe(1);
    });
    it("image has additional class hero__image--single if single size image is used", () => {
      const { container } = render(
        <Hero image={{ src: "text-img-single" }} title="test-title" />,
      );
      expect(
        container.getElementsByClassName("hero__image--single").length,
      ).toBe(1);
    });
    it("image has additional class hero__image--fullwidth if prop hasFullwidthImage is passed", () => {
      const { container } = render(
        <Hero image={image} hasFullwidthImage title="test-title" />,
      );
      expect(
        container.getElementsByClassName("hero__image--fullwidth").length,
      ).toBe(1);
    });
    it("image's attribute src is set to image.default", () => {
      const { container } = render(<Hero image={image} title="test-title" />);
      expect(container.querySelector("img").getAttribute("src")).toBe(
        "test-img",
      );
    });
    it("image's attribute src is set to image.src if passed as single image", () => {
      const { container } = render(
        <Hero image={{ src: "test-img-single" }} title="test-title" />,
      );
      expect(container.querySelector("img").getAttribute("src")).toBe(
        "test-img-single",
      );
    });
    ["test-img-xxl", "test-img-xl", "test-img-lg", "test-img-sm"].map(
      (size, index) => {
        it(`${
          index + 1
        }. source element has attribute srcSet is set to ${size}`, () => {
          const { container } = render(
            <Hero image={image} title="test-title" />,
          );
          expect(
            container.querySelectorAll("source")[index].getAttribute("srcSet"),
          ).toBe(size);
        });
      },
    );
    it("image wrapper with class hero__image-wrapper is rendered", () => {
      const { container } = render(<Hero image={image} title="test-title" />);
      expect(
        container.getElementsByClassName("hero__image-wrapper").length,
      ).toBe(1);
    });
    it("image has additional class hero__image--gradient when prop hasGradientOverlay is passed", () => {
      const { container } = render(
        <Hero hasGradientOverlay image={image} title="test-title" />,
      );
      expect(
        container.getElementsByClassName("hero__image--gradient").length,
      ).toBe(1);
    });
    it("image has additional class hero__image--gradient-halfwidth when prop hasGradientOverlay is passed", () => {
      const { container } = render(
        <Hero hasGradientOverlay image={image} title="test-title" />,
      );
      expect(
        container.getElementsByClassName("hero__image--gradient-halfwidth")
          .length,
      ).toBe(1);
    });
    it("image doesn't have class hero__image--gradient-halfwidth when prop hasFullwidthImage is also passed", () => {
      const { container } = render(
        <Hero
          hasGradientOverlay
          hasFullwidthImage
          image={image}
          title="test-title"
        />,
      );
      expect(
        container.getElementsByClassName("hero__image--gradient-halfwidth")
          .length,
      ).toBe(0);
    });
  });
});
