162 lines
4.7 KiB
TypeScript
162 lines
4.7 KiB
TypeScript
import { render, screen, within } from "@testing-library/react";
|
|
import type { ReactNode } from "react";
|
|
import {
|
|
getFeaturedProjects,
|
|
type PortfolioProjectView,
|
|
} from "@/lib/portfolio-data";
|
|
import Projects from "./Projects";
|
|
|
|
jest.mock("motion/react", () => {
|
|
const React = require("react");
|
|
const motion = new Proxy(
|
|
{},
|
|
{
|
|
get: (_, tag: string) => {
|
|
const Component = ({
|
|
children,
|
|
animate: _animate,
|
|
initial: _initial,
|
|
transition: _transition,
|
|
variants: _variants,
|
|
viewport: _viewport,
|
|
whileHover: _whileHover,
|
|
whileInView: _whileInView,
|
|
whileTap: _whileTap,
|
|
...props
|
|
}: { children?: ReactNode } & Record<string, unknown>) =>
|
|
React.createElement(tag, props, children);
|
|
Component.displayName = `motion.${tag}`;
|
|
return Component;
|
|
},
|
|
},
|
|
);
|
|
|
|
return { motion };
|
|
});
|
|
|
|
jest.mock("@/app/hooks/useReducedMotion", () => ({
|
|
useReducedMotion: () => true,
|
|
}));
|
|
|
|
jest.mock("./animations/DrawLine", () => ({
|
|
DrawLine: () => null,
|
|
}));
|
|
|
|
jest.mock("./Section", () => ({
|
|
Section: ({ children, title }: { children: ReactNode; title: string }) => (
|
|
<section>
|
|
<h2>{title}</h2>
|
|
{children}
|
|
</section>
|
|
),
|
|
}));
|
|
|
|
const [baseProject] = getFeaturedProjects(null);
|
|
const projects: PortfolioProjectView[] = [
|
|
{
|
|
...baseProject,
|
|
id: "available-demo",
|
|
title: "Demo disponível",
|
|
description: "Descrição disponível",
|
|
technologies: ["Stack disponível"],
|
|
status: "Disponível",
|
|
demoUrl: "https://available.example",
|
|
githubUrl: "https://github.com/example/available",
|
|
demoAvailability: "available",
|
|
demoCheckedAt: "2026-09-04T12:00:00.000Z",
|
|
},
|
|
{
|
|
...baseProject,
|
|
id: "unavailable-demo",
|
|
title: "Demo indisponível",
|
|
description: "Descrição indisponível",
|
|
technologies: ["Stack indisponível"],
|
|
status: "Indisponível",
|
|
demoUrl: "https://unavailable.example",
|
|
githubUrl: "https://github.com/example/unavailable",
|
|
demoAvailability: "unavailable",
|
|
demoCheckedAt: "2026-09-04T12:00:00.000Z",
|
|
},
|
|
{
|
|
...baseProject,
|
|
id: "unknown-demo",
|
|
title: "Demo desconhecida",
|
|
description: "Descrição desconhecida",
|
|
technologies: ["Stack desconhecida"],
|
|
status: "Não verificada",
|
|
demoUrl: "https://unknown.example",
|
|
githubUrl: "https://github.com/example/unknown",
|
|
demoAvailability: "unknown",
|
|
demoCheckedAt: null,
|
|
},
|
|
{
|
|
...baseProject,
|
|
id: "no-demo",
|
|
title: "Projeto sem demo",
|
|
description: "Descrição sem demo",
|
|
technologies: ["Stack sem demo"],
|
|
status: "Sem demo",
|
|
demoUrl: null,
|
|
githubUrl: "https://github.com/example/no-demo",
|
|
demoAvailability: "none",
|
|
demoCheckedAt: null,
|
|
},
|
|
];
|
|
|
|
describe("Projects", () => {
|
|
it("renders demo actions according to availability", () => {
|
|
render(<Projects projects={projects} />);
|
|
|
|
expect(
|
|
screen.getByRole("heading", { name: "Demo disponível" }),
|
|
).toBeVisible();
|
|
expect(screen.getByRole("link", { name: "Abrir projeto" })).toHaveAttribute(
|
|
"href",
|
|
"https://available.example",
|
|
);
|
|
|
|
const unavailable = screen.getByText(
|
|
"Demo indisponível na última verificação",
|
|
);
|
|
expect(unavailable).toHaveAttribute("aria-disabled", "true");
|
|
expect(unavailable).not.toHaveAttribute("href");
|
|
expect(unavailable.closest("a")).toBeNull();
|
|
|
|
expect(
|
|
screen.getByRole("link", {
|
|
name: /Abrir projeto.*Disponibilidade não verificada/i,
|
|
}),
|
|
).toHaveAttribute("href", "https://unknown.example");
|
|
|
|
const noDemoCard = screen
|
|
.getByRole("heading", { name: "Projeto sem demo" })
|
|
.closest("article");
|
|
expect(noDemoCard).not.toBeNull();
|
|
expect(
|
|
within(noDemoCard as HTMLElement).queryByRole("link", {
|
|
name: /Abrir projeto/i,
|
|
}),
|
|
).not.toBeInTheDocument();
|
|
});
|
|
|
|
it("keeps project evidence visible when the demo is unavailable", () => {
|
|
render(<Projects projects={projects} />);
|
|
|
|
const card = screen
|
|
.getByRole("heading", { name: "Demo indisponível" })
|
|
.closest("article");
|
|
expect(card).not.toBeNull();
|
|
const unavailableCard = within(card as HTMLElement);
|
|
|
|
expect(unavailableCard.getByText("Descrição indisponível")).toBeVisible();
|
|
expect(unavailableCard.getByText("Stack indisponível")).toBeVisible();
|
|
expect(unavailableCard.getByText("Indisponível")).toBeVisible();
|
|
expect(
|
|
unavailableCard.getByRole("link", { name: "Ver codigo" }),
|
|
).toHaveAttribute("href", "https://github.com/example/unavailable");
|
|
expect(
|
|
unavailableCard.queryByRole("link", { name: /Abrir projeto/i }),
|
|
).not.toBeInTheDocument();
|
|
});
|
|
});
|