Skip to content

Commit 4374c4a

Browse files
committed
feat: enhance server tests with static directory handling and fallback SPA logic
1 parent eace90b commit 4374c4a

2 files changed

Lines changed: 141 additions & 1 deletion

File tree

backend/tests/integration/jobsApi.test.js

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,27 @@ import { mkdtempSync } from "fs";
22
import { tmpdir } from "os";
33
import { join } from "path";
44
import request from "supertest";
5-
import { afterEach, describe, expect, it } from "vitest";
5+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
66
import XLSX from "xlsx";
7+
8+
const mocks = vi.hoisted(() => ({
9+
run: vi.fn(),
10+
}));
11+
12+
vi.mock("../../src/app.js", () => ({
13+
run: mocks.run,
14+
}));
15+
716
import { createJobsApiApp } from "../../src/jobsApiApp.js";
817

918
describe("jobs API", () => {
1019
let tmpDir;
1120

21+
beforeEach(() => {
22+
vi.clearAllMocks();
23+
mocks.run.mockResolvedValue(undefined);
24+
});
25+
1226
afterEach(() => {
1327
tmpDir = undefined;
1428
});
@@ -63,4 +77,67 @@ describe("jobs API", () => {
6377
const res = await request(app).get("/api/jobs").query({ file: "nao-existe.xlsx" }).expect(404);
6478
expect(res.body.message).toBe("Arquivo solicitado nao encontrado.");
6579
});
80+
81+
it("POST /api/scraper/run executa scraper e retorna metadados", async () => {
82+
tmpDir = mkdtempSync(join(tmpdir(), "jobs-api-"));
83+
const workbook = XLSX.utils.book_new();
84+
const sheet = XLSX.utils.json_to_sheet([{ titulo: "x" }]);
85+
XLSX.utils.book_append_sheet(workbook, sheet, "Vagas");
86+
XLSX.writeFile(workbook, join(tmpDir, "resultado.xlsx"));
87+
88+
const app = createJobsApiApp({ outputDir: tmpDir });
89+
const res = await request(app).post("/api/scraper/run").expect(200);
90+
91+
expect(mocks.run).toHaveBeenCalledTimes(1);
92+
expect(res.body.ok).toBe(true);
93+
expect(res.body.file).toBe("resultado.xlsx");
94+
expect(res.body.totalFiles).toBe(1);
95+
});
96+
97+
it("POST /api/scraper/run retorna 409 quando ja existe execucao ativa", async () => {
98+
tmpDir = mkdtempSync(join(tmpdir(), "jobs-api-"));
99+
let finishRun;
100+
mocks.run.mockImplementation(
101+
() =>
102+
new Promise((resolve) => {
103+
finishRun = resolve;
104+
}),
105+
);
106+
107+
const app = createJobsApiApp({ outputDir: tmpDir });
108+
109+
const firstRequest = new Promise((resolve, reject) => {
110+
request(app)
111+
.post("/api/scraper/run")
112+
.end((error, response) => {
113+
if (error) {
114+
reject(error);
115+
return;
116+
}
117+
resolve(response);
118+
});
119+
});
120+
121+
await vi.waitFor(() => {
122+
expect(mocks.run).toHaveBeenCalledTimes(1);
123+
});
124+
125+
const conflict = await request(app).post("/api/scraper/run").expect(409);
126+
expect(conflict.body.message).toBe("O scraper ja esta em execucao.");
127+
128+
finishRun();
129+
const firstResult = await firstRequest;
130+
expect(firstResult.status).toBe(200);
131+
});
132+
133+
it("POST /api/scraper/run retorna 500 quando scraper falha", async () => {
134+
tmpDir = mkdtempSync(join(tmpdir(), "jobs-api-"));
135+
mocks.run.mockRejectedValue(new Error("falha no scraper"));
136+
137+
const app = createJobsApiApp({ outputDir: tmpDir });
138+
const res = await request(app).post("/api/scraper/run").expect(500);
139+
140+
expect(res.body.message).toBe("Erro ao executar o scraper.");
141+
expect(res.body.error).toBe("falha no scraper");
142+
});
66143
});

backend/tests/unit/services/server.test.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,45 @@
1+
import path from "path";
12
import { beforeEach, describe, expect, it, vi } from "vitest";
23

34
const mocks = vi.hoisted(() => ({
45
listen: vi.fn(),
6+
use: vi.fn(),
57
createJobsApiApp: vi.fn(),
68
consoleLog: vi.fn(),
9+
existsSync: vi.fn(),
10+
staticMiddleware: vi.fn(),
11+
expressStatic: vi.fn(),
712
}));
813

914
mocks.createJobsApiApp.mockReturnValue({
1015
listen: mocks.listen,
16+
use: mocks.use,
1117
});
1218

19+
mocks.expressStatic.mockReturnValue(mocks.staticMiddleware);
20+
1321
vi.mock("../../../src/jobsApiApp.js", () => ({
1422
createJobsApiApp: mocks.createJobsApiApp,
1523
}));
1624

25+
vi.mock("fs", () => ({
26+
existsSync: mocks.existsSync,
27+
}));
28+
29+
vi.mock("express", () => ({
30+
default: {
31+
static: mocks.expressStatic,
32+
},
33+
}));
34+
1735
describe("server entry", () => {
1836
beforeEach(() => {
1937
vi.resetModules();
2038
vi.clearAllMocks();
2139
process.env.PORT = "3100";
40+
delete process.env.ELECTRON_STATIC_DIR;
41+
delete process.env.ELECTRON_OUTPUT_DIR;
42+
mocks.existsSync.mockReturnValue(false);
2243
vi.spyOn(console, "log").mockImplementation(mocks.consoleLog);
2344
});
2445

@@ -41,4 +62,46 @@ describe("server entry", () => {
4162

4263
expect(mocks.listen).toHaveBeenCalledWith(3001, expect.any(Function));
4364
});
65+
66+
it("usa ELECTRON_OUTPUT_DIR quando definido", async () => {
67+
process.env.ELECTRON_OUTPUT_DIR = "/tmp/electron-output";
68+
69+
await import("../../../src/server.js");
70+
71+
expect(mocks.createJobsApiApp).toHaveBeenCalledWith({
72+
outputDir: "/tmp/electron-output",
73+
});
74+
});
75+
76+
it("registra static e fallback SPA quando ELECTRON_STATIC_DIR existe", async () => {
77+
process.env.ELECTRON_STATIC_DIR = "/tmp/frontend-dist";
78+
mocks.existsSync.mockReturnValue(true);
79+
80+
await import("../../../src/server.js");
81+
82+
expect(mocks.expressStatic).toHaveBeenCalledWith("/tmp/frontend-dist");
83+
expect(mocks.use).toHaveBeenCalledTimes(2);
84+
expect(mocks.use).toHaveBeenNthCalledWith(1, mocks.staticMiddleware);
85+
86+
const fallbackHandler = mocks.use.mock.calls[1][0];
87+
88+
const apiRes = {
89+
status: vi.fn().mockReturnThis(),
90+
json: vi.fn(),
91+
sendFile: vi.fn(),
92+
};
93+
fallbackHandler({ path: "/api/unknown" }, apiRes);
94+
expect(apiRes.status).toHaveBeenCalledWith(404);
95+
expect(apiRes.json).toHaveBeenCalledWith({ error: "Rota não encontrada." });
96+
expect(apiRes.sendFile).not.toHaveBeenCalled();
97+
98+
const pageRes = {
99+
status: vi.fn().mockReturnThis(),
100+
json: vi.fn(),
101+
sendFile: vi.fn(),
102+
};
103+
fallbackHandler({ path: "/dashboard" }, pageRes);
104+
expect(pageRes.sendFile).toHaveBeenCalledWith(path.join("/tmp/frontend-dist", "index.html"));
105+
expect(pageRes.status).not.toHaveBeenCalled();
106+
});
44107
});

0 commit comments

Comments
 (0)