feat(home): prova no topo, contato sem atrito e conversão medida
Home mais curta (hero, vitrine de clientes, sobre, serviços, IA resumida, depoimentos e contato), faixa de clientes e telas reais no hero, sem números do GitHub. Barra de cookies fina, WhatsApp fixo no celular, formulário com e-mail opcional e alternativa por e-mail, página /ia, eventos de e-mail, redes e currículo e conversão do Ads opcional por variável. Rodapé em 3 colunas. Remove componentes órfãos (LighthouseMetrics, Skills, Experience, contagem do GitHub).
This commit is contained in:
1 parent
6e1022b58c
commit
8d07b8c6bb
60 files changed
+4392
-2124
No files matched your search
@@ -1,7 +1,14 @@
|
||||
import { fireEvent, render, screen } from "@testing-library/react";
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
import Hero, { roundedRepoFloor } from "./Hero";
|
||||
import Hero from "./Hero";
|
||||
|
||||
const clients = [
|
||||
{ id: "sev-modaintima", name: "SEV Moda Íntima" },
|
||||
{ id: "lavacao-047", name: "Lavação 047" },
|
||||
{ id: "sc-plus", name: "SC Plus Aquicultura" },
|
||||
{ id: "as-servicos", name: "AS Serviços" },
|
||||
];
|
||||
|
||||
jest.mock("motion/react", () => {
|
||||
const React = require("react");
|
||||
@@ -60,61 +67,75 @@ describe("Hero", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps social destinations with isolated external tabs", () => {
|
||||
it("keeps the single LinkedIn profile and the e-mail, with no GitHub link", () => {
|
||||
render(<Hero />);
|
||||
|
||||
expect(screen.getByRole("link", { name: "GitHub" })).toHaveAttribute(
|
||||
"href",
|
||||
"https://github.com/evandrodevbr",
|
||||
);
|
||||
expect(screen.getByRole("link", { name: "LinkedIn" })).toHaveAttribute(
|
||||
"href",
|
||||
"https://www.linkedin.com/in/evandro-fonseca-junior-0969aa1b0/",
|
||||
"https://www.linkedin.com/in/evandrodevbr/",
|
||||
);
|
||||
expect(screen.getByRole("link", { name: "Email" })).toHaveAttribute(
|
||||
"href",
|
||||
"mailto:[email protected]",
|
||||
);
|
||||
for (const name of ["GitHub", "LinkedIn"]) {
|
||||
const link = screen.getByRole("link", { name });
|
||||
expect(link).toHaveAttribute("target", "_blank");
|
||||
expect(link).toHaveAttribute("rel", "noopener noreferrer");
|
||||
const linkedin = screen.getByRole("link", { name: "LinkedIn" });
|
||||
expect(linkedin).toHaveAttribute("target", "_blank");
|
||||
expect(linkedin).toHaveAttribute("rel", "noopener noreferrer");
|
||||
expect(screen.queryByRole("link", { name: "GitHub" })).toBeNull();
|
||||
for (const link of screen.getAllByRole("link")) {
|
||||
expect(link.getAttribute("href") ?? "").not.toMatch(/github\.com/);
|
||||
}
|
||||
});
|
||||
|
||||
it("shows the real GitHub repo count with the public/private breakdown", () => {
|
||||
render(<Hero stats={{ repos: { total: 68, public: 25, private: 43 } }} />);
|
||||
|
||||
expect(screen.getByText("projetos desenvolvidos")).toBeInTheDocument();
|
||||
expect(screen.getByText("Mais de")).toBeInTheDocument();
|
||||
expect(screen.getByText("65")).toBeInTheDocument();
|
||||
expect(screen.getByText("25 públicos · 43 privados")).toBeInTheDocument();
|
||||
expect(screen.queryByText(/projetos publicados/i)).not.toBeInTheDocument();
|
||||
expect(screen.queryByText(/demonstração online/i)).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("rounds the repo count down so 'mais de' is always true", () => {
|
||||
expect(roundedRepoFloor(68)).toBe(65);
|
||||
expect(roundedRepoFloor(66)).toBe(65);
|
||||
expect(roundedRepoFloor(65)).toBe(60);
|
||||
expect(roundedRepoFloor(6)).toBe(5);
|
||||
expect(roundedRepoFloor(5)).toBe(0);
|
||||
});
|
||||
|
||||
it("hides the repo count while the total is too small to round", () => {
|
||||
render(<Hero stats={{ repos: { total: 4, public: 2, private: 2 } }} />);
|
||||
it("states who the work is for and how the contact works", () => {
|
||||
render(<Hero />);
|
||||
|
||||
expect(
|
||||
screen.queryByText(/projetos desenvolvidos/i),
|
||||
).not.toBeInTheDocument();
|
||||
screen.getByText(
|
||||
"Para empresas que cresceram além das planilhas e dos sistemas prontos: sites, sistemas web, aplicativos e integrações, com contato direto com quem desenvolve.",
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
expect(screen.getByRole("link", { name: /conversar/i })).toHaveAttribute(
|
||||
"id",
|
||||
"hero-contact-cta",
|
||||
);
|
||||
});
|
||||
|
||||
it("omits the repo count when the GitHub lookup is unavailable", () => {
|
||||
it("shows only the years of experience, with no repository numbers", () => {
|
||||
render(<Hero stats={{ years: 5 }} />);
|
||||
|
||||
expect(screen.getByText("anos de experiência")).toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByText(/projetos desenvolvidos/i),
|
||||
).not.toBeInTheDocument();
|
||||
expect(screen.getByText("5")).toBeInTheDocument();
|
||||
expect(screen.queryByText(/projetos desenvolvidos/i)).toBeNull();
|
||||
expect(screen.queryByText(/públicos|privados|mais de/i)).toBeNull();
|
||||
});
|
||||
|
||||
it("lists the delivered clients, each linking to its case", () => {
|
||||
render(<Hero clients={clients} />);
|
||||
|
||||
expect(screen.getByText("Já entregue para:")).toBeInTheDocument();
|
||||
for (const { id, name } of clients) {
|
||||
expect(screen.getByRole("link", { name })).toHaveAttribute(
|
||||
"href",
|
||||
`/cases/${id}`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("renders the work column with lazy posters that stay out of small screens", () => {
|
||||
render(<Hero clients={clients} />);
|
||||
|
||||
const work = screen.getByTestId("hero-work");
|
||||
expect(work).toHaveClass("hidden", "lg:block");
|
||||
const images = work.querySelectorAll("img");
|
||||
expect(images).toHaveLength(2);
|
||||
for (const image of images) {
|
||||
expect(image).toHaveAttribute("loading", "lazy");
|
||||
}
|
||||
expect(images[0]).toHaveAttribute(
|
||||
"src",
|
||||
"/videos/lavacao-047/desktop.webp",
|
||||
);
|
||||
expect(images[1]).toHaveAttribute("src", "/videos/as-servicos/mobile.webp");
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user