Skip to content

Develop - #22

Merged
Benevanio merged 5 commits into
masterfrom
develop
Mar 24, 2026
Merged

Benevanio merged 5 commits into
masterfrom
develop

Conversation

@Benevanio

Copy link
Copy Markdown
Collaborator

No description provided.

…e.js

- Added package.json with project metadata, dependencies, and build scripts.
- Created loading.html for a loading screen with a spinner and status message.
- Implemented main.js to manage the Electron app lifecycle, including backend startup and health checks.
- Added preload.js for potential IPC helpers in the future.
#20)

…e.js

- Added package.json with project metadata, dependencies, and build
scripts.
- Created loading.html for a loading screen with a spinner and status
message.
- Implemented main.js to manage the Electron app lifecycle, including
backend startup and health checks.
- Added preload.js for potential IPC helpers in the future.
Copilot AI review requested due to automatic review settings March 24, 2026 18:52
@Benevanio
Benevanio merged commit 6a73fd8 into master Mar 24, 2026
4 checks passed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the monorepo to support a Windows desktop distribution via Electron, embedding the existing Express backend and React UI into a packaged app and adding a UI-triggered scraper run.

Changes:

  • Adds Electron main process boot flow (start backend in-process, wait for health, load UI) plus loading window assets.
  • Introduces POST /api/scraper/run in the backend and wires a “Buscar vagas” action in the frontend to trigger it.
  • Updates root packaging/build setup (electron-builder config, scripts) and documents the desktop workflow.

Reviewed changes

Copilot reviewed 12 out of 14 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
package.json Adds Electron scripts, electron-builder config, and app metadata for desktop distribution.
frontend/src/services/jobsService.ts Adds runScraperRequest() calling POST /api/scraper/run.
frontend/src/hooks/useJobsData.ts Adds scraper state + triggerScraper() to run scraper and refresh available XLSX files/jobs.
frontend/src/App.tsx Adds “Buscar vagas” button with spinner state and disables UI during scraping.
electron/preload.js Adds preload placeholder (no IPC exposed yet).
electron/main.js Implements Electron boot flow, backend start + health polling, loading window, and main window.
electron/loading.html Adds a dedicated loading screen shown while backend starts.
backend/src/jobsApiApp.js Adds POST /api/scraper/run with a single-run concurrency guard.
backend/src/server.js Adds Electron-specific output/static directory handling and SPA fallback routing.
backend/tests/unit/services/server.test.js Adds tests for ELECTRON_* env behavior and SPA fallback.
backend/tests/integration/jobsApi.test.js Adds integration tests for /api/scraper/run success, conflict, and failure cases.
README.md Documents how to run/build/distribute the Electron app.
.gitignore Ignores dist-electron/.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread backend/src/jobsApiApp.js
Comment on lines +111 to +115
try {
activeScraperRun = runScraper();
await activeScraperRun;

const files = listXlsxFiles();

Copilot AI Mar 24, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

runScraper() usa getConfig() (que lê OUTPUT_FILE/PDF_FILE do process.env) para decidir onde gravar os arquivos, mas este endpoint lista/retorna arquivos a partir de outputDir (opção do createJobsApiApp). Se outputDir for customizado (ex.: em testes/uso embutido), o scraper pode escrever em outro diretório e a resposta pode não refletir o resultado do run. Considere alinhar o diretório de output do scraper com outputDir (passando config para o scraper ou setando env defaults com base em outputDir).

Copilot uses AI. Check for mistakes.
Comment thread backend/src/server.js
// Router (if used in future) works correctly.
app.use((req, res) => {
if (req.path.startsWith("/api")) {
return res.status(404).json({ error: "Rota não encontrada." });

Copilot AI Mar 24, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

O fallback para rotas /api/* está retornando { error: ... }, mas o frontend (e os demais endpoints) usam o campo message para exibir erros. Para manter consistência e garantir que readMessage(payload) funcione, troque para { message: "Rota não encontrada." } (e ajuste o teste correspondente).

Suggested change
return res.status(404).json({ error: "Rota não encontrada." });
return res.status(404).json({ message: "Rota não encontrada." });

Copilot uses AI. Check for mistakes.
};
fallbackHandler({ path: "/api/unknown" }, apiRes);
expect(apiRes.status).toHaveBeenCalledWith(404);
expect(apiRes.json).toHaveBeenCalledWith({ error: "Rota não encontrada." });

Copilot AI Mar 24, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Este teste valida o fallback SPA com { error: "Rota não encontrada." }, mas a API e o frontend padronizam mensagens de erro no campo message. Após ajustar o middleware em backend/src/server.js para usar message, atualize esta asserção para refletir o payload correto.

Suggested change
expect(apiRes.json).toHaveBeenCalledWith({ error: "Rota não encontrada." });
expect(apiRes.json).toHaveBeenCalledWith({ message: "Rota não encontrada." });

Copilot uses AI. Check for mistakes.
Comment thread electron/main.js
Comment on lines +180 to +182
dialog.showErrorBox(
'Falha ao iniciar o aplicativo',
`O servidor não pôde ser iniciado.\n\n${fatal.message}`,

Copilot AI Mar 24, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No catch, o template string acessa fatal.message, mas fatal pode não ser um Error (por exemplo, um string/objeto). Isso pode causar uma exceção dentro do próprio handler de erro e impedir a exibição do dialog. Faça um narrowing (ex.: fatal instanceof Error) e faça fallback para String(fatal)/mensagem padrão.

Suggested change
dialog.showErrorBox(
'Falha ao iniciar o aplicativo',
`O servidor não pôde ser iniciado.\n\n${fatal.message}`,
let fatalMessage;
if (fatal instanceof Error && typeof fatal.message === 'string' && fatal.message) {
fatalMessage = fatal.message;
} else if (fatal != null) {
fatalMessage = String(fatal);
} else {
fatalMessage = 'Erro desconhecido.';
}
dialog.showErrorBox(
'Falha ao iniciar o aplicativo',
`O servidor não pôde ser iniciado.\n\n${fatalMessage}`,

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants