import { ComponentFixture, TestBed } from "@angular/core/testing";

import { Employment } from "../config/Employment";
import { JobTypeDescriptions, JobTypes } from "../config/Icons";

import { JobComponent } from "./job.component";

describe("JobComponent", () => {
  let component: JobComponent;
  let fixture: ComponentFixture<JobComponent>;
  let compiled: HTMLElement;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [JobComponent]
    }).compileComponents();

    fixture = TestBed.createComponent(JobComponent);
    component = fixture.componentInstance;
    compiled = fixture.nativeElement;
  });

  for (const expected of Employment) {
    it("should parse properties correctly", () => {
      component.job = expected;
      component.align = "left";
      fixture.detectChanges();
      expect(component.job).toBe(expected);
      expect(component.align).toBe("left");
      expect(component.type).toBe(
        expected.type === "hypothetical"
          ? "hypothetical"
          : expected.end
            ? "former"
            : "current"
      );
      expect(component.icon).toBe(JobTypes[expected.type]);
      expect(component.iconDescription).toBe(
        JobTypeDescriptions[expected.type]
      );
      expect(component.expanded).toBeFalse();
      expect(component.description).toEqual(expected.description.split(/\n+/));
      expect(component.date).toBe(
        expected.end
          ? `${expected.start.toLocaleDateString("en-GB", {
              month: "long",
              year: "numeric"
            })} - ${expected.end.toLocaleDateString("en-GB", {
              month: "long",
              year: "numeric"
            })}`
          : expected.start.toLocaleDateString("en-GB", {
              month: "long",
              year: "numeric"
            })
      );
    });

    it("should render a job correctly", () => {
      component.job = expected;
      component.ngOnInit();
      fixture.detectChanges();
      compiled = fixture.nativeElement;

      /* Button wrapper */
      const button = compiled.querySelector("button");
      expect(button?.classList).toContain("left");
      expect(button?.classList).toContain(
        expected.type === "hypothetical"
          ? "hypothetical"
          : expected.end
            ? "former"
            : "current"
      );

      /* Timeline Icon */
      const icon = compiled.querySelector("fa-icon");
      expect(icon?.classList).toContain("icon");
      expect(icon?.classList).toContain(
        expected.type === "hypothetical"
          ? "hypothetical"
          : expected.end
            ? "former"
            : "current"
      );
      const svg = icon?.querySelector("svg");
      const path = svg?.querySelector("path");
      expect(path?.getAttribute("d")).toBe(
        JobTypes[expected.type].icon[4] as string
      );

      /* Rendered content from job object */
      const title = compiled.querySelector("h2");
      expect(title?.innerText.trim()).toBe(expected.title);
      const classList = compiled.querySelector("button")?.classList;
      expect(classList).toContain(
        expected.type === "hypothetical"
          ? "hypothetical"
          : expected.end
            ? "former"
            : "current"
      );
      const date = compiled.querySelector(".date");
      expect(date?.textContent?.trim()).toBe(
        expected.end
          ? `${expected.start.toLocaleDateString("en-GB", {
              month: "long",
              year: "numeric"
            })} - ${expected.end.toLocaleDateString("en-GB", {
              month: "long",
              year: "numeric"
            })}`
          : expected.start.toLocaleDateString("en-GB", {
              month: "long",
              year: "numeric"
            })
      );

      /* Test the stuff that's hidden */
      const article = compiled.querySelector("article");
      expect(article).toBeNull();
      const logo = compiled.querySelector(".logo");
      expect(logo).toBeNull();
      const iconDescription = compiled.querySelector(".desc");
      expect(iconDescription).toBeNull();
    });

    it("should expand a job correctly", () => {
      component.job = expected;
      component.ngOnInit();
      if (!component.expanded) {
        component.expand();
      }
      fixture.detectChanges();
      compiled = fixture.nativeElement;

      expect(component.expanded).toBeTrue();

      /* Button wrapper */
      const button = compiled.querySelector("button");
      expect(button?.classList).toContain("left");
      expect(button?.classList).toContain(
        expected.type === "hypothetical"
          ? "hypothetical"
          : expected.end
            ? "former"
            : "current"
      );

      /* Timeline Icon */
      const icon = compiled.querySelector("fa-icon");
      expect(icon?.classList).toContain("icon");
      expect(icon?.classList).toContain(
        expected.type === "hypothetical"
          ? "hypothetical"
          : expected.end
            ? "former"
            : "current"
      );
      const svg = icon?.querySelector("svg");
      const path = svg?.querySelector("path");
      expect(path?.getAttribute("d")).toBe(
        JobTypes[expected.type].icon[4] as string
      );

      /* Rendered content from job object should NOT be changed */
      const title = compiled.querySelector("h2");
      expect(title?.innerText.trim()).toBe(expected.title);
      const classList = compiled.querySelector("button")?.classList;
      expect(classList).toContain(
        expected.type === "hypothetical"
          ? "hypothetical"
          : expected.end
            ? "former"
            : "current"
      );
      const date = compiled.querySelector(".date");
      expect(date?.textContent?.trim()).toBe(
        expected.end
          ? `${expected.start.toLocaleDateString("en-GB", {
              month: "long",
              year: "numeric"
            })} - ${expected.end.toLocaleDateString("en-GB", {
              month: "long",
              year: "numeric"
            })}`
          : expected.start.toLocaleDateString("en-GB", {
              month: "long",
              year: "numeric"
            })
      );

      /* Hidden stuff should now be visible */
      const article = compiled.querySelector("article");
      expect(article?.innerText.replace(/\n+/g, "\n")).toBe(
        expected.description
          .split(/\n+/)
          .map((el) => el.trim())
          .join("\n")
      );

      if (expected.logo) {
        const logo = compiled.querySelector(".logo");
        expect(logo?.getAttribute("src")).toBe(
          `/assets/img/icons/${expected.logo}`
        );
        expect(logo?.classList).toContain("logo");
      }

      const iconDescription = compiled.querySelector(".desc");
      expect(iconDescription?.textContent?.trim()).toBe(
        JobTypeDescriptions[expected.type]
      );
    });
  }
});
