import { readFileSync } from "node:fs"; import { join } from "node:path"; import { caseStudies, clientCases, getRelatedCases, getRelatedServices, isClientCase, labCases, servicePages, } from "./site-content"; const clientIds = ["sev-modaintima", "lavacao-047", "sc-plus", "as-servicos"]; const labIds = ["nutriscan", "twins-lab", "reddit-explorer", "gcc-installer"]; function getService(slug: string) { const service = servicePages.find((item) => item.slug === slug); if (!service) throw new Error(`Missing service ${slug}`); return service; } it("separates client work from the laboratory using the kind in the portfolio data", () => { expect(clientCases.map(({ id }) => id)).toEqual(clientIds); expect(labCases.map(({ id }) => id)).toEqual(labIds); expect(caseStudies).toHaveLength(8); expect( caseStudies.every( (item) => isClientCase(item) === clientIds.includes(item.id), ), ).toBe(true); expect(isClientCase({ id: "projeto-que-nao-existe" })).toBe(false); }); it("gives every case the sections of the business structure", () => { for (const caseStudy of caseStudies) { expect(caseStudy.headline.length).toBeGreaterThan(10); expect(caseStudy.context.length).toBeGreaterThan(20); expect(caseStudy.problem.length).toBeGreaterThan(20); expect(caseStudy.deliveries.length).toBeGreaterThanOrEqual(3); expect(caseStudy.stack.length).toBeGreaterThan(0); expect(caseStudy.decisions.length).toBeGreaterThan(0); // sem dado real e autorizado, não há seção de resultado expect(caseStudy.result).toBeUndefined(); } }); it("writes the NutriScan case in business language", () => { expect(caseStudies.find(({ id }) => id === "nutriscan")?.headline).toBe( "Consulta de alimentos por nome ou código de barras", ); }); it("has no GitHub link, source list or disqualifying caveat in the public text", () => { const text = JSON.stringify({ caseStudies, servicePages }); expect(text).not.toMatch(/github\.com/i); expect(text).not.toMatch(/\/#contact/); expect(text).not.toMatch( /Limites desta evidência|Desafio verificável|Exemplos ilustrativos|não projetos já entregues|Sem promessas|nem CI|não há CI|escopo definido|não comprova|não representa/i, ); for (const caseStudy of caseStudies) { expect(caseStudy).not.toHaveProperty("githubUrl"); expect(caseStudy).not.toHaveProperty("detail"); } }); it("never mentions an unavailable demo in the case text", () => { expect(JSON.stringify(caseStudies)).not.toMatch(/indispon/i); }); it("leaves the commercial offer of every service empty for the owner to fill in", () => { for (const service of servicePages) { expect(service.startingPrice).toBeUndefined(); expect(service.typicalTimeline).toBeUndefined(); expect(service.guarantee).toBeUndefined(); } }); it("mentions the region and a benefit in the title and description of every service", () => { for (const service of servicePages) { expect(`${service.seoTitle} ${service.metaDescription}`).toMatch( /Garuva|Joinville|Santa Catarina/, ); expect(service.metaDescription).toMatch(/remoto|Brasil/); } const descriptions = servicePages.map( ({ metaDescription }) => metaDescription, ); expect(new Set(descriptions).size).toBe(descriptions.length); }); it("maps each service to its client cases", () => { expect(getService("criacao-de-sites").relatedCaseIds).toEqual(clientIds); expect(getService("engenharia-de-software").relatedCaseIds).toEqual([ "sev-modaintima", "lavacao-047", ]); expect(getService("consultoria-nextjs").relatedCaseIds).toEqual([ "sev-modaintima", "lavacao-047", "sc-plus", ]); expect(getService("arquitetura-de-software").relatedCaseIds).toEqual([ "sev-modaintima", ]); // GCC Installer é Python/Tkinter: não combina com um serviço de Tauri e Rust expect(getService("tauri-rust").relatedCaseIds).toEqual([]); expect(getService("integracao-hardware-software-iot").relatedCaseIds).toEqual( ["twins-lab"], ); }); it("puts client cases before laboratory cases when listing related work", () => { expect( getRelatedCases(["twins-lab", "lavacao-047", "sev-modaintima"]).map( ({ id }) => id, ), ).toEqual(["lavacao-047", "sev-modaintima", "twins-lab"]); expect(getRelatedCases(["nao-existe"])).toEqual([]); }); it("derives the exact related service set from the existing relationship", () => { expect(getRelatedServices("twins-lab").map(({ slug }) => slug)).toEqual([ "integracao-hardware-software-iot", ]); expect( getRelatedServices("sev-modaintima") .map(({ slug }) => slug) .sort(), ).toEqual( [ "criacao-de-sites", "engenharia-de-software", "consultoria-nextjs", "arquitetura-de-software", ].sort(), ); expect(getRelatedServices("gcc-installer")).toEqual([]); }); 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 without a public site and states the author's participation", () => { const asServicos = caseStudies.find(({ id }) => id === "as-servicos"); expect(asServicos?.demoUrl).toBeNull(); 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); }); it("keeps site-content and the modules it imports free of Node built-ins, so client components can import it", () => { for (const file of [ "site-content", "portfolio-data", "proof", "project-health", ]) { const source = readFileSync(join(__dirname, `${file}.ts`), "utf8"); expect(source).not.toMatch(/from "node:/); } });