Conversation
- Define OUTPUT_FILE e PDF_FILE padrão em output/ - Garante criação do diretório pai antes de gerar XLSX/PDF - Atualiza README com os caminhos padrão Made-with: Cursor
fix: arquivos de exportação padrão na pasta output/
- Extrai createJobsApiApp para testar Express sem subir porta - Testes de getConfig e rotas /api (health, jobs, 404) - Scripts npm test, validate e validate:ci - Workflow CI em pull_request e push (master, develop) - README: secao Testes e CI e estrutura do projeto Made-with: Cursor
feat(ci): testes automatizados (Vitest) e workflow no GitHub Actions
There was a problem hiding this comment.
Pull request overview
This PR introduces a backend testing + CI setup (Vitest/Supertest) and refactors the Express jobs API into a reusable app factory to enable testable API routes, while also standardizing default output paths under output/.
Changes:
- Add Vitest configuration and new backend tests for config parsing and jobs API endpoints.
- Refactor Express API setup into
createJobsApiApp()and simplifysrc/server.jsto an entrypoint. - Ensure exporter creates parent directories for Excel/PDF outputs; update defaults/docs and add a CI workflow.
Reviewed changes
Copilot reviewed 10 out of 11 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| vitest.config.js | Adds Vitest config (node environment). |
| test/jobsApi.test.js | Adds Supertest-based API tests for health/jobs endpoints. |
| test/config.test.js | Adds unit tests for getConfig() defaults and env parsing. |
| src/server.js | Refactors to use createJobsApiApp() and only start the server. |
| src/jobsApiApp.js | New reusable Express app factory containing API routes. |
| src/exporter.js | Ensures parent directories exist before writing Excel/PDF outputs. |
| src/config.js | Changes default output paths to output/.... |
| package.json | Adds vitest/supertest scripts and devDependencies; adds validate scripts. |
| package-lock.json | Locks new devDependencies (vitest/supertest) and transitive deps. |
| README.md | Documents new files, CI/validation commands, and updated output defaults. |
| .github/workflows/ci.yml | Adds CI workflow running backend tests + frontend lint/build. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| on: | ||
| pull_request: | ||
| push: | ||
| branches: [master, develop] |
There was a problem hiding this comment.
O workflow roda em push apenas para branches [master, develop], mas o repositório parece usar 'main' como branch base (vide diffs). Isso faz com que pushes diretos em main não executem o CI. Sugestão: incluir 'main' na lista (ou ajustar para o branch padrão real) para garantir validação em push.
| branches: [master, develop] | |
| branches: [main, master, develop] |
| const files = listXlsxFiles().map(({ file, modifiedAt, size }) => ({ | ||
| file, | ||
| modifiedAt, | ||
| size, | ||
| })); | ||
|
|
||
| res.json({ files }); |
There was a problem hiding this comment.
A rota GET /api/jobs/files chama listXlsxFiles() (readdirSync/statSync) sem try/catch. Em caso de erro de permissão, arquivo removido entre readdirSync e statSync, etc., a resposta tende a ser um 500 padrão do Express (possivelmente HTML) e não o JSON padronizado usado em /api/jobs. Sugestão: envolver a lógica da rota em try/catch e retornar um erro JSON consistente.
| const files = listXlsxFiles().map(({ file, modifiedAt, size }) => ({ | |
| file, | |
| modifiedAt, | |
| size, | |
| })); | |
| res.json({ files }); | |
| try { | |
| const files = listXlsxFiles().map(({ file, modifiedAt, size }) => ({ | |
| file, | |
| modifiedAt, | |
| size, | |
| })); | |
| return res.json({ files }); | |
| } catch (error) { | |
| return res.status(500).json({ | |
| message: "Erro ao listar arquivos de vagas.", | |
| error: error?.message || "Erro desconhecido", | |
| }); | |
| } |
| let tmpDir; | ||
|
|
||
| afterEach(() => { | ||
| tmpDir = undefined; | ||
| }); |
There was a problem hiding this comment.
Os testes criam diretórios temporários com mkdtempSync, mas o afterEach apenas zera a variável e não remove o diretório/arquivos. Isso pode acumular lixo em /tmp e causar flakiness em execuções repetidas/CI. Sugestão: no afterEach, remover tmpDir com fs.rmSync(tmpDir, { recursive: true, force: true }) quando definido (e só então setar undefined).
No description provided.