Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 62 additions & 124 deletions frontend/src/services/authService.ts
Original file line number Diff line number Diff line change
@@ -1,65 +1,45 @@
/* eslint-disable @typescript-eslint/no-explicit-any */

function normalizeBaseUrl(value: string | undefined): string {
return typeof value === "string" ? value.trim().replace(/\/+$/, "") : "";
}
function getBaseUrl(): string {
const base = import.meta.env.VITE_API_BASE_URL;

function getApiBaseUrl(): string {
const configuredBaseUrl = normalizeBaseUrl(import.meta.env.VITE_API_BASE_URL);
if (configuredBaseUrl) {
console.log("Usando VITE_API_BASE_URL:", configuredBaseUrl);
return configuredBaseUrl;
if (base && base.trim().length > 0) {
return base.replace(/\/+$/, "");
}
console.log(" Sem VITE_API_BASE_URL, usando caminho relativo");

return "";
}

function buildApiUrl(path: string): string {
function buildUrl(path: string): string {
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
const baseUrl = getApiBaseUrl();
const fullUrl = baseUrl ? `${baseUrl}${normalizedPath}` : normalizedPath;
console.log(" Construindo URL:", { path, baseUrl, fullUrl });
return fullUrl;
const base = getBaseUrl();

return base ? `${base}${normalizedPath}` : normalizedPath;
}

async function readPayload(response: Response): Promise<Record<string, unknown>> {
const contentType = response.headers?.get?.("content-type") ?? "";
console.log(" Content-Type:", contentType);

if (!contentType || contentType.includes("application/json")) {
try {
const payload = await response.json();
console.log(" Payload JSON:", payload);
return payload && typeof payload === "object"
? (payload as Record<string, unknown>)
: {};
} catch (error) {
console.log(" Erro ao parsear JSON:", error);
return {};
async function parseResponse(response: Response) {
const contentType = response.headers.get("content-type") ?? "";

try {
if (contentType.includes("application/json")) {
return await response.json();
}
}

if (typeof response.text === "function") {

const text = await response.text();
console.log("Resposta texto:", text);
return text ? { message: text } : {};
} catch {
return {};
}

return {};
}

function buildError(message: unknown, fallback: string): Error {
const errorMsg = typeof message === "string" && message ? message : fallback;
console.error("Erro construído:", errorMsg);
return new Error(errorMsg);
function extractMessage(payload: any): string | undefined {
return payload?.message && typeof payload.message === "string"
? payload.message
: undefined;
}

function readMessage(payload: unknown): string | undefined {
if (payload && typeof payload === "object" && "message" in payload) {
const message = (payload as { message?: unknown }).message;
if (typeof message === "string") return message;
}
return undefined;
function createError(payload: any, fallback: string) {
return new Error(extractMessage(payload) || fallback);
}

export interface LoginCredentials {
Expand All @@ -75,113 +55,71 @@ export interface RegisterData {
cpf?: string;
}

export async function login(credentials: LoginCredentials): Promise<{ token?: string; user?: any; message?: string }> {
console.log("Iniciando login com:", { email: credentials.email });
const url = buildApiUrl("/api/auth/login");
console.log("URL:", url);
console.log("Método: POST");

const response = await fetch(url, {
export async function login(credentials: LoginCredentials) {
const response = await fetch(buildUrl("/api/auth/login"), {
method: "POST",
headers: {
"Content-Type": "application/json",
},
headers: { "Content-Type": "application/json" },
body: JSON.stringify(credentials),
credentials: "include",
});

console.log("Status da resposta:", response.status);
console.log("Status text:", response.statusText);

const payload = await readPayload(response);


const payload = await parseResponse(response);

if (!response.ok) {
console.error("Login falhou:", payload);
throw buildError(readMessage(payload), "Falha ao fazer login.");
throw createError(payload, "Falha ao fazer login.");
}

console.log("Login bem sucedido:", payload);

return payload;
}

export async function register(userData: RegisterData): Promise<{ message?: string; user?: any }> {
console.log("Iniciando registro com:", { email: userData.email, name: userData.name });
const url = buildApiUrl("/api/auth/register");
console.log("URL:", url);
console.log("Método: POST");

const bodyData = {
email: userData.email,
password: userData.password,
name: userData.name,
};
console.log("Body enviado:", bodyData);

const response = await fetch(url, {
export async function register(userData: RegisterData) {
const response = await fetch(buildUrl("/api/auth/register"), {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(bodyData),
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
email: userData.email,
password: userData.password,
name: userData.name,
phone: userData.phone,
cpf: userData.cpf,
}),
credentials: "include",
});

console.log("Status da resposta:", response.status);
console.log("Status text:", response.statusText);
console.log("Headers:", {
contentType: response.headers.get("content-type"),
cors: response.headers.get("access-control-allow-origin"),
});

const payload = await readPayload(response);


const payload = await parseResponse(response);

if (!response.ok) {
console.error(" Registro falhou:", { status: response.status, payload });
throw buildError(readMessage(payload), `Falha ao cadastrar: ${response.status} ${response.statusText}`);
throw createError(payload, "Falha ao cadastrar.");
}

console.log(" Registro bem sucedido:", payload);

return payload;
}

export async function logout(): Promise<void> {
console.log(" Iniciando logout");
const url = buildApiUrl("/api/auth/logout");
console.log(" URL:", url);

const response = await fetch(url, {
export async function logout() {
const response = await fetch(buildUrl("/api/auth/logout"), {
method: "POST",
credentials: "include",
});
console.log(" Status:", response.status);

const payload = await parseResponse(response);

if (!response.ok) {
const payload = await readPayload(response);
console.error(" Logout falhou:", payload);
throw buildError(readMessage(payload), "Falha ao fazer logout.");
throw createError(payload, "Falha ao fazer logout.");
}
console.log("Logout bem sucedido");

return payload;
}

export async function getCurrentUser(): Promise<any> {
console.log("🚀 Buscando usuário atual");
const url = buildApiUrl("/api/auth/me");
console.log("URL:", url);

const response = await fetch(url, {
export async function getCurrentUser() {
const response = await fetch(buildUrl("/api/auth/me"), {
credentials: "include",
});

console.log("📡 Status:", response.status);
const payload = await readPayload(response);


const payload = await parseResponse(response);

if (!response.ok) {
console.error(" Busca falhou:", payload);
throw buildError(readMessage(payload), "Falha ao carregar usuário.");
throw createError(payload, "Falha ao carregar usuário.");
}

console.log(" Usuário encontrado:", payload);

return payload;
}
12 changes: 0 additions & 12 deletions frontend/tests/unit/hooks/useJobsData.extended.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,18 +94,6 @@ describe("useJobsData extended", () => {
expect(result.current.scraping).toBe(false);
});

it("triggerScraper propaga erro inesperado", async () => {
mocks.runScraperRequestMock.mockRejectedValueOnce("erro-desconhecido");

const { result } = renderHook(() => useJobsData());

await act(async () => {
await result.current.triggerScraper();
});

expect(result.current.error).toMatch(/erro inesperado ao executar o scraper/i);
});

it("triggerScraper atualiza selectedFile quando novo arquivo é diferente do atual", async () => {
mocks.fetchJobFilesMock
.mockResolvedValueOnce([{ file: "vagas.xlsx" }])
Expand Down
Loading
Loading