import { render, screen } from "@testing-library/react";
import Footer from "./Footer";
describe("Footer Component - Contact Information", () => {
it("should render contact section heading", () => {
render();
const contactHeading = screen.getByText("Contato direto");
expect(contactHeading).toBeInTheDocument();
expect(contactHeading.tagName).toBe("H3");
});
it("should render email address", () => {
render();
const emailLink = screen.getByText("evandro@dev.br");
expect(emailLink).toBeInTheDocument();
expect(emailLink.tagName).toBe("A");
});
it("should have mailto link for email", () => {
render();
const emailLink = screen.getByText("evandro@dev.br");
expect(emailLink).toHaveAttribute("href", "mailto:evandro@dev.br");
});
it("should apply correct styling classes to email link", () => {
render();
const emailLink = screen.getByText("evandro@dev.br");
const classes = emailLink.className;
expect(classes).toContain("text-[12px]");
expect(classes).toContain("hover:text-[var(--slash)]");
});
});
describe("Footer Component - Social Links", () => {
it("should render social links section heading", () => {
render();
const connectHeading = screen.getByText("Redes profissionais");
expect(connectHeading).toBeInTheDocument();
expect(connectHeading.tagName).toBe("H3");
});
it("should render GitHub social link", () => {
render();
const githubLink = screen.getByLabelText("Visit GitHub profile");
expect(githubLink).toBeInTheDocument();
expect(githubLink.tagName).toBe("A");
});
it("should render LinkedIn social link", () => {
render();
const linkedinLink = screen.getByLabelText("Visit LinkedIn profile");
expect(linkedinLink).toBeInTheDocument();
expect(linkedinLink.tagName).toBe("A");
});
it("should have correct href for GitHub link", () => {
render();
const githubLink = screen.getByLabelText("Visit GitHub profile");
expect(githubLink).toHaveAttribute(
"href",
"https://github.com/evandrodevbr",
);
});
it("should have correct href for LinkedIn link", () => {
render();
const linkedinLink = screen.getByLabelText("Visit LinkedIn profile");
expect(linkedinLink).toHaveAttribute(
"href",
"https://linkedin.com/in/evandrodevbr",
);
});
it('should open social links in new tab with target="_blank"', () => {
render();
const githubLink = screen.getByLabelText("Visit GitHub profile");
const linkedinLink = screen.getByLabelText("Visit LinkedIn profile");
expect(githubLink).toHaveAttribute("target", "_blank");
expect(linkedinLink).toHaveAttribute("target", "_blank");
});
it('should have rel="noopener noreferrer" for security', () => {
render();
const githubLink = screen.getByLabelText("Visit GitHub profile");
const linkedinLink = screen.getByLabelText("Visit LinkedIn profile");
expect(githubLink).toHaveAttribute("rel", "noopener noreferrer");
expect(linkedinLink).toHaveAttribute("rel", "noopener noreferrer");
});
it("should have aria-label for accessibility", () => {
render();
const githubLink = screen.getByLabelText("Visit GitHub profile");
const linkedinLink = screen.getByLabelText("Visit LinkedIn profile");
expect(githubLink).toHaveAttribute("aria-label", "Visit GitHub profile");
expect(linkedinLink).toHaveAttribute(
"aria-label",
"Visit LinkedIn profile",
);
});
it("should render SVG icons for social links", () => {
render();
const githubLink = screen.getByLabelText("Visit GitHub profile");
const linkedinLink = screen.getByLabelText("Visit LinkedIn profile");
const githubSvg = githubLink.querySelector("svg");
const linkedinSvg = linkedinLink.querySelector("svg");
expect(githubSvg).toBeInTheDocument();
expect(linkedinSvg).toBeInTheDocument();
});
it('should have aria-hidden="true" on SVG icons', () => {
render();
const githubLink = screen.getByLabelText("Visit GitHub profile");
const linkedinLink = screen.getByLabelText("Visit LinkedIn profile");
const githubSvg = githubLink.querySelector("svg");
const linkedinSvg = linkedinLink.querySelector("svg");
expect(githubSvg).toHaveAttribute("aria-hidden", "true");
expect(linkedinSvg).toHaveAttribute("aria-hidden", "true");
});
});
describe("Footer Component - Copyright", () => {
it("should render copyright section heading", () => {
render();
const copyrightHeading = screen.getByText("Informacoes legais");
expect(copyrightHeading).toBeInTheDocument();
expect(copyrightHeading.tagName).toBe("H3");
});
it("should display current year in copyright text", () => {
render();
const currentYear = new Date().getFullYear();
const copyrightText = screen.getByText(
new RegExp(`© ${currentYear} Evandro Fonseca Junior`),
);
expect(copyrightText).toBeInTheDocument();
});
it("should update copyright year dynamically", () => {
// Test that the component uses new Date().getFullYear() dynamically
// by verifying it shows the current year (not a hardcoded value)
const currentYear = new Date().getFullYear();
render();
// Verify the copyright includes the current year
const copyrightText = screen.getByText(
new RegExp(`© ${currentYear} Evandro Fonseca Junior`),
);
expect(copyrightText).toBeInTheDocument();
// Verify it's not hardcoded to a specific year like 2023 or 2024
// by checking that the year matches the actual current year
expect(currentYear).toBeGreaterThanOrEqual(2024);
});
it("should apply correct styling to copyright text", () => {
render();
const currentYear = new Date().getFullYear();
const copyrightText = screen.getByText(
new RegExp(`© ${currentYear} Evandro Fonseca Junior`),
);
const classes = copyrightText.className;
expect(classes).toContain("text-[12px]");
expect(classes).toContain("text-[rgba(255,255,255,0.5)]");
});
});
describe("Footer Component - Responsive Layout", () => {
beforeEach(() => {
// Mock window.matchMedia for responsive tests
Object.defineProperty(window, "matchMedia", {
writable: true,
value: jest.fn().mockImplementation((query) => ({
matches: false,
media: query,
onchange: null,
addListener: jest.fn(),
removeListener: jest.fn(),
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
})),
});
});
it("should have responsive grid layout classes", () => {
const { container } = render();
const gridContainer = container.querySelector(".grid");
expect(gridContainer).toBeInTheDocument();
const classes = gridContainer?.className || "";
expect(classes).toContain("grid-cols-1");
expect(classes).toContain("md:grid-cols-2");
expect(classes).toContain("lg:grid-cols-3");
});
it("should have responsive padding classes on container", () => {
const { container } = render();
const innerContainer = container.querySelector(".ds-section-shell");
expect(innerContainer).toBeInTheDocument();
// The ds-section class handles responsive padding via CSS
const footer = container.querySelector("footer");
const classes = footer?.className || "";
expect(classes).toContain("ds-section");
});
it("should have responsive gap classes on grid", () => {
const { container } = render();
const gridContainer = container.querySelector(".grid");
const classes = gridContainer?.className || "";
expect(classes).toContain("gap-sp-6");
});
it("should have responsive column span for copyright section", () => {
const { container } = render();
// Find the copyright section by its heading
const copyrightHeading = screen.getByText("Informacoes legais");
const copyrightSection = copyrightHeading.closest(".ds-card");
expect(copyrightSection).toBeInTheDocument();
const classes = copyrightSection?.className || "";
expect(classes).toContain("md:col-span-2");
expect(classes).toContain("lg:col-span-1");
});
});
describe("Footer Component - Design System Consistency", () => {
it("should use design system kicker class for section labels", () => {
render();
const kickers = document.querySelectorAll(".ds-kicker");
expect(kickers.length).toBeGreaterThan(0);
});
it("should have ds-section class on footer element", () => {
const { container } = render();
const footer = container.querySelector("footer");
expect(footer).toBeInTheDocument();
const classes = footer?.className || "";
expect(classes).toContain("ds-section");
});
it("should have ds-section-dark class for dark background", () => {
const { container } = render();
const footer = container.querySelector("footer");
const classes = footer?.className || "";
expect(classes).toContain("ds-section-dark");
});
it("should use design system shell class for container", () => {
const { container } = render();
const shell = container.querySelector(".ds-section-shell");
expect(shell).toBeInTheDocument();
});
});
describe("Footer Component - Structure", () => {
it("should render as footer semantic element", () => {
const { container } = render();
const footer = container.querySelector("footer");
expect(footer).toBeInTheDocument();
});
it("should have three main sections", () => {
render();
const contactHeading = screen.getByText("Contato direto");
const connectHeading = screen.getByText("Redes profissionais");
const copyrightHeading = screen.getByText("Informacoes legais");
expect(contactHeading).toBeInTheDocument();
expect(connectHeading).toBeInTheDocument();
expect(copyrightHeading).toBeInTheDocument();
});
it("should have design system shell container", () => {
const { container } = render();
const innerContainer = container.querySelector(".ds-section-shell");
expect(innerContainer).toBeInTheDocument();
});
});