Job e2e separado no CI; testes de teclado, rolagem, sem JS, axe no celular e menu do celular; limites de metadados derivados do sitemap; sai @react-three/fiber e @react-three/drei; pastas de ferramentas (.augment, .kiro, .claude/settings.local.json) fora do Git.
57 lines
1.9 KiB
TypeScript
57 lines
1.9 KiB
TypeScript
import { readdirSync, readFileSync } from "node:fs";
|
|
import { join } from "node:path";
|
|
|
|
const root = join(__dirname, "..");
|
|
|
|
/** Arquivos de código (fora dos testes) de app/ e lib/ cuja primeira instrução é a diretiva "use client". */
|
|
function findClientFiles() {
|
|
return ["app", "lib"]
|
|
.flatMap((dir) =>
|
|
readdirSync(join(root, dir), { recursive: true, encoding: "utf8" }).map(
|
|
(file) => `${dir}/${file.replaceAll("\\", "/")}`,
|
|
),
|
|
)
|
|
.filter(
|
|
(file) =>
|
|
/\.tsx?$/.test(file) &&
|
|
!/\.test\.tsx?$/.test(file) &&
|
|
/^\s*["']use client["']/.test(readFileSync(join(root, file), "utf8")),
|
|
)
|
|
.sort();
|
|
}
|
|
|
|
describe("fronteira entre servidor e cliente", () => {
|
|
it.each([
|
|
"app/cases/_components/case-media.ts",
|
|
"lib/og-card.tsx",
|
|
"lib/portfolio-data.server.ts",
|
|
])("%s só pode ser importado no servidor", (file) => {
|
|
const source = readFileSync(join(root, file), "utf8");
|
|
expect(source).toMatch(/^import "server-only";$/m);
|
|
});
|
|
|
|
it("declara server-only como dependência", () => {
|
|
const manifest = JSON.parse(
|
|
readFileSync(join(root, "package.json"), "utf8"),
|
|
) as { dependencies: Record<string, string> };
|
|
expect(manifest.dependencies["server-only"]).toBeDefined();
|
|
});
|
|
|
|
it("não deixa nenhum componente de cliente importar um módulo só de servidor", () => {
|
|
const serverOnly =
|
|
/from "(?:@\/lib\/og-card|@\/lib\/portfolio-data\.server|(?:\.{1,2}\/)+(?:[\w-]+\/)*case-media)"/;
|
|
const clientFiles = findClientFiles();
|
|
// a busca precisa achar os componentes de cliente que existem, senão o teste passaria vazio
|
|
expect(clientFiles).toEqual(
|
|
expect.arrayContaining([
|
|
"app/cases/_components/CasePlayer.tsx",
|
|
"app/curriculo/CvDownloadLink.tsx",
|
|
]),
|
|
);
|
|
for (const file of clientFiles) {
|
|
const source = readFileSync(join(root, file), "utf8");
|
|
expect(source).not.toMatch(serverOnly);
|
|
}
|
|
});
|
|
});
|