Files
portifolio-evandrodevbr/lib/site-content.test.ts
Evandro Fonseca JuniorandClaude Sonnet 5.5 02ecba73f8 feat(cases): Reddit Posts Explorer e MinGW GCC Installer com resposta, desafio, implementacao, limites e fontes fixadas em commit
- textos reescritos a partir do codigo e do README dos repositorios publicos (SHA ff76e08 e bab64fc); remove afirmacoes que o codigo nao sustenta (SSG, rate limiting/cache, busca em tempo real, download assincrono, monitoramento)
- public/portfolio-data.json alinhado (descricao, tecnologias, recursos e selos)
- testes: cinco cases detalhados, limite sourced + escopo editorial, guardas contra afirmacoes sem fonte

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-05 00:00:42 -03:00

123 lines
3.8 KiB
TypeScript

import { caseStudies, getRelatedServices, servicePages } from "./site-content";
const detailedIds = [
"as-servicos",
"gcc-installer",
"nutriscan",
"reddit-explorer",
"twins-lab",
] as const;
const immutableGitHubBlobUrl =
/^https:\/\/github\.com\/[^/]+\/[^/]+\/blob\/[0-9a-f]{40}\/.+$/;
function getDetail(id: (typeof detailedIds)[number]) {
const detail = caseStudies.find((item) => item.id === id)?.detail;
expect(detail).toBeDefined();
if (!detail) throw new Error(`Missing detail for ${id}`);
return detail;
}
it("limits detailed content to the evidenced cases (public repositories pinned to a commit)", () => {
expect(
caseStudies
.filter(({ detail }) => detail !== undefined)
.map(({ id }) => id)
.sort(),
).toEqual([...detailedIds].sort());
});
it("uses unique source IDs and immutable GitHub commit URLs", () => {
for (const id of detailedIds) {
const { sources } = getDetail(id);
const sourceIds = sources.map(({ id }) => id);
expect(new Set(sourceIds).size).toBe(sourceIds.length);
for (const { url } of sources) {
expect(url).toMatch(immutableGitHubBlobUrl);
}
}
});
it("requires sources for factual statements and resolves every source ID", () => {
for (const id of detailedIds) {
const detail = getDetail(id);
const sourceIds = new Set(detail.sources.map(({ id }) => id));
const factualStatements = [
detail.answer,
detail.challenge,
...detail.implementation,
];
for (const statement of [...factualStatements, ...detail.boundaries]) {
expect(
statement.sourceIds.every((sourceId) => sourceIds.has(sourceId)),
).toBe(true);
}
for (const statement of factualStatements) {
expect(statement.sourceIds.length).toBeGreaterThan(0);
}
}
expect(
getDetail("as-servicos").boundaries.map(({ sourceIds }) => sourceIds),
).toEqual([[]]);
for (const id of ["nutriscan", "twins-lab"] as const) {
expect(
getDetail(id).boundaries.every(({ sourceIds }) => sourceIds.length > 0),
).toBe(true);
}
expect(getDetail("nutriscan").boundaries[0]?.sourceIds).toContain(
"nutri-readme",
);
// reddit-explorer e gcc-installer: o 1º limite vem da documentação do repositório; o 2º é o escopo editorial (sem fonte)
for (const id of ["reddit-explorer", "gcc-installer"] as const) {
const { boundaries } = getDetail(id);
expect(boundaries[0]?.sourceIds.length).toBeGreaterThan(0);
expect(boundaries.slice(1).every(({ sourceIds }) => sourceIds.length === 0)).toBe(true);
}
});
it("derives the exact related service set from the existing relationship", () => {
expect(
getRelatedServices("twins-lab")
.map(({ slug }) => slug)
.sort(),
).toEqual(
[
"consultoria-nextjs",
"integracao-hardware-software-iot",
"arquitetura-de-software",
].sort(),
);
});
it("resolves every declared related case ID", () => {
const caseIds = new Set(caseStudies.map(({ id }) => id));
const unresolved = servicePages.flatMap(({ slug, relatedCaseIds }) =>
relatedCaseIds
.filter((caseId) => !caseIds.has(caseId))
.map((caseId) => ({ slug, caseId })),
);
expect(unresolved).toEqual([]);
});
it("does not publish the unavailable Twins Lab demo", () => {
expect(
caseStudies.find((item) => item.id === "twins-lab")?.demoUrl,
).toBeUndefined();
});
it("keeps AS Serviços as a project (code only) and states the author's participation", () => {
const asServicos = caseStudies.find(({ id }) => id === "as-servicos");
expect(asServicos?.demoUrl).toBeNull();
expect(asServicos?.githubUrl).toBe(
"https://github.com/evandrodevbr/as-servicos",
);
expect(asServicos?.role).toMatch(/primeira landing page/i);
expect(asServicos?.role).toMatch(/animações 3D/i);
expect(asServicos?.role).toMatch(/painel para controle de projetos/i);
});