Skip to content

Commit 46e4d83

Browse files
committed
Integration test
1 parent f3aece6 commit 46e4d83

File tree

5 files changed

+216
-67
lines changed

5 files changed

+216
-67
lines changed

nodeapp/app.js

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,8 @@ import * as agentsController from "./controllers/agentsController.js";
1010
import * as sessionManager from "./lib/sessionManager.js";
1111
import * as ejs from "ejs";
1212

13-
// Usar una forma compatible con entornos de test para obtener __dirname
14-
let dirname;
15-
try {
16-
dirname = path.dirname(fileURLToPath(import.meta.url));
17-
} catch (error) {
18-
// Fallback para entornos de test
19-
dirname = ".";
20-
}
13+
const __filename = fileURLToPath(import.meta.url);
14+
const __dirname = path.dirname(__filename);
2115

2216
const app = express();
2317

@@ -29,7 +23,7 @@ app.locals.appName = "NodeApp";
2923

3024
app.use(logger("dev"));
3125
app.use(express.urlencoded({ extended: false }));
32-
app.use(express.static(path.join(dirname, "public")));
26+
app.use(express.static(path.join(__dirname, "public")));
3327

3428
/**
3529
* Application routes
@@ -42,23 +36,12 @@ app.post("/login", loginController.postLogin);
4236
app.get("/logout", loginController.logout);
4337
app.get("/agents/new", sessionManager.guard, agentsController.index);
4438
app.post("/agents/new", sessionManager.guard, agentsController.postNew);
45-
app.get(
46-
"/agents/delete/:agentId",
47-
sessionManager.guard,
48-
agentsController.deleteAgent
49-
);
39+
app.get("/agents/delete/:agentId", sessionManager.guard, agentsController.deleteAgent);
5040

5141
// Ejemplos
5242
app.get("/param_in_route/:num?", homeController.paranInRoute);
53-
app.get(
54-
"/param_in_route_multiple/:product/size/:size([0-9]+)/color/:color",
55-
homeController.paranInRouteMultiple
56-
);
57-
app.get(
58-
"/param_in_query",
59-
homeController.validateParamInQuery,
60-
homeController.paramInQuery
61-
);
43+
app.get("/param_in_route_multiple/:product/size/:size([0-9]+)/color/:color", homeController.paranInRouteMultiple);
44+
app.get("/param_in_query", homeController.validateParamInQuery, homeController.paramInQuery);
6245
app.post("/post_with_body", homeController.postWithBody);
6346

6447
// catch 404 and send error

nodeapp/controllers/agents.controller.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import request from "supertest";
2-
import app from "../app";
2+
import app from "../app.js";
33
import { guard, middleware } from "../lib/sessionManager";
44

55
// Podemos mockear funciones internas

nodeapp/controllers/loginController.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,22 @@ export async function postLogin(req, res, next) {
1212
const redir = req.query.redir;
1313
// buscar el usuario en la base de datos
1414
const user = await User.findOne({ email: email });
15-
console.log(user);
15+
//console.log(user);
1616

1717
// si no lo encuentro, o la contraseña no coincide --> error
1818
if (!user || !(await user.comparePassword(password))) {
19-
console.log(
20-
`Login failed for user ${email}: user not found or password mismatch`
21-
);
19+
console.log(`Login failed for user ${email}: user not found or password mismatch`);
2220
res.locals.error = "Invalid credentials";
2321
res.locals.email = email;
2422
res.render("login");
25-
console.log(`Login failed for user ${email}`);
23+
//console.log(`Login failed for user ${email}`);
2624
return;
2725
}
2826

2927
// Registrar el inicio de sesión
3028
const ip = req.ip || req.connection.remoteAddress;
3129
user.addLoginRecord(ip);
32-
console.log(`Login record added for user ${user.email} from IP ${ip}`);
30+
//console.log(`Login record added for user ${user.email} from IP ${ip}`);
3331
await user.save();
3432

3533
// si el usuario existe y la contraseña es buena --> redirect a la home
Lines changed: 139 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,141 @@
1+
import request from "supertest";
2+
import app from "../app";
3+
import User from "../models/User";
4+
5+
jest.mock("../models/User.js");
6+
7+
// Mockeamos connectMongoose para evitar conexiones reales
8+
jest.mock("../lib/connectMongoose.js", () => {
9+
return jest.fn().mockResolvedValue({
10+
name: "mockConnection",
11+
close: jest.fn(),
12+
});
13+
});
14+
15+
// Mockeamos session para evitar problemas de sesión
16+
jest.mock("express-session", () => {
17+
return () => (req, res, next) => {
18+
req.session = {
19+
userId: null,
20+
regenerate: jest.fn((cb) => cb(null)),
21+
};
22+
next();
23+
};
24+
});
25+
26+
// Mockeamos sessionManager para simplificar los tests
27+
jest.mock("../lib/sessionManager", () => ({
28+
middleware: (req, res, next) => {
29+
req.session = {
30+
userId: null,
31+
regenerate: jest.fn((cb) => cb(null)),
32+
};
33+
next();
34+
},
35+
useSessionInViews: (req, res, next) => {
36+
res.locals.session = req.session || {};
37+
next();
38+
},
39+
guard: (req, res, next) => next(),
40+
}));
41+
142
describe("loginController", () => {
2-
it.todo("debe devolver un 200 al visitar la página de login");
43+
// Limpiamos mocks antes de cada test
44+
beforeEach(() => {
45+
jest.clearAllMocks();
46+
});
47+
48+
it("debe devolver un 200 al visitar la página de login", async () => {
49+
const response = await request(app).get("/login");
50+
51+
expect(response.status).toBe(200);
52+
});
53+
54+
it("debe mostrar formulario de login sin errores inicialmente", async () => {
55+
const response = await request(app).get("/login");
56+
57+
expect(response.text).toContain("form");
58+
expect(response.text).not.toContain("Invalid credentials");
59+
});
60+
61+
it("debe redirigir a home tras login exitoso", async () => {
62+
// Mock de usuario existente con contraseña correcta
63+
const mockUser = {
64+
id: "user123",
65+
email: "test@example.com",
66+
comparePassword: jest.fn().mockResolvedValue(true),
67+
addLoginRecord: jest.fn(),
68+
save: jest.fn().mockResolvedValue(true),
69+
};
70+
71+
User.findOne = jest.fn().mockResolvedValue(mockUser);
72+
73+
const response = await request(app).post("/login").type("form").send({
74+
email: "test@example.com",
75+
password: "password123",
76+
});
77+
78+
expect(response.status).toBe(302);
79+
expect(response.headers.location).toBe("/");
80+
expect(User.findOne).toHaveBeenCalledWith({ email: "test@example.com" });
81+
expect(mockUser.comparePassword).toHaveBeenCalledWith("password123");
82+
});
83+
84+
it("debe mostrar error con credenciales inválidas", async () => {
85+
// Mock de usuario existente con contraseña incorrecta
86+
const mockUser = {
87+
email: "test@example.com",
88+
comparePassword: jest.fn().mockResolvedValue(false),
89+
};
90+
91+
User.findOne = jest.fn().mockResolvedValue(mockUser);
92+
93+
const response = await request(app).post("/login").type("form").send({
94+
email: "test@example.com",
95+
password: "wrongpassword",
96+
});
97+
98+
expect(response.status).toBe(200);
99+
expect(response.text).toContain("Invalid credentials");
100+
});
101+
102+
it("debe mostrar error cuando el usuario no existe", async () => {
103+
// Mock de usuario no existente
104+
User.findOne = jest.fn().mockResolvedValue(null);
105+
106+
const response = await request(app).post("/login").type("form").send({
107+
email: "nonexistent@example.com",
108+
password: "anypassword",
109+
});
110+
111+
expect(response.status).toBe(200);
112+
expect(response.text).toContain("Invalid credentials");
113+
});
114+
115+
it("debe redirigir a la URL especificada después del login exitoso", async () => {
116+
// Mock de usuario existente con contraseña correcta
117+
const mockUser = {
118+
id: "user123",
119+
email: "test@example.com",
120+
comparePassword: jest.fn().mockResolvedValue(true),
121+
addLoginRecord: jest.fn(),
122+
save: jest.fn().mockResolvedValue(true),
123+
};
124+
125+
User.findOne = jest.fn().mockResolvedValue(mockUser);
126+
127+
const response = await request(app).post("/login?redir=/agents/new").type("form").send({
128+
email: "test@example.com",
129+
password: "password123",
130+
});
131+
132+
expect(response.status).toBe(302);
133+
expect(response.headers.location).toBe("/agents/new");
134+
});
135+
it("debe cerrar sesión y redirigir a home al hacer logout", async () => {
136+
const response = await request(app).get("/logout");
137+
138+
expect(response.status).toBe(302);
139+
expect(response.headers.location).toBe("/");
140+
});
3141
});

nodeapp/models/Agent.test.js

Lines changed: 66 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,71 @@
1-
import Agent from "./Agent.js";
2-
3-
describe("Agent Model & schema", () => {
4-
it("Deberia requerir un nombre y una edad valida", async () => {
5-
let error;
6-
// Crear un agente incorrecto
7-
const agent = new Agent({
8-
name: "John Doe",
9-
age: -5, // Edad inválida
10-
});
11-
try {
12-
//Validarlo
13-
await agent.validate();
14-
} catch (er) {
15-
error = er;
16-
}
17-
//Asegurarnos de que no pasa la validación
18-
console.log(error);
19-
expect(error).toBeDefined();
20-
expect(error.errors.age).toBeDefined();
1+
import request from "supertest";
2+
import app from "../app.js";
3+
import Agent from "../models/Agent.js";
4+
5+
// Mockeamos el modelo Agent
6+
jest.mock("../models/Agent.js");
7+
8+
// Mockeamos connectMongoose para evitar conexiones reales
9+
jest.mock("../lib/connectMongoose.js", () => {
10+
return jest.fn().mockResolvedValue({
11+
name: "mockConnection",
12+
close: jest.fn(),
2113
});
14+
});
15+
16+
// Mockeamos session para evitar problemas de sesión
17+
jest.mock("express-session", () => {
18+
return () => (req, res, next) => {
19+
req.session = { userId: null };
20+
next();
21+
};
22+
});
23+
24+
// Mockeamos sessionManager para simplificar los tests
25+
jest.mock("../lib/sessionManager", () => ({
26+
middleware: (req, res, next) => {
27+
req.session = { userId: null };
28+
next();
29+
},
30+
useSessionInViews: (req, res, next) => {
31+
res.locals.session = req.session || {};
32+
next();
33+
},
34+
guard: (req, res, next) => next(),
35+
}));
36+
37+
describe("homeController", () => {
38+
// Test de integración usando supertest
39+
describe("Pruebas de integración", () => {
40+
// Configuramos los mocks antes de cada test
41+
beforeEach(() => {
42+
// Configuramos el mock de Agent.find para que devuelva una lista de agentes de prueba
43+
Agent.find = jest.fn().mockResolvedValue([
44+
{ _id: "agent1", name: "Smith", age: 45 },
45+
{ _id: "agent2", name: "Brown", age: 33 },
46+
]);
47+
});
48+
49+
it("debe devolver un 200 al visitar la home", async () => {
50+
expect.assertions(1);
51+
let response;
52+
try {
53+
response = await request(app).get("/");
54+
} catch (ex) {
55+
console.log("Error al hacer la petición");
56+
console.log(ex);
57+
}
58+
59+
expect(response.status).toBe(200);
60+
}, 15000); // Aumentamos el timeout a 15 segundos
61+
62+
it("debe llamar a Agent.find con los parámetros correctos", async () => {
63+
// Realizamos la petición a la ruta /
64+
expect.assertions(1);
65+
await request(app).get("/");
2266

23-
it("deberia aceptar una edad valida", async () => {
24-
let error;
25-
// Crear un agente incorrecto
26-
const agent = new Agent({
27-
name: "John Two",
28-
age: 19, // Edad inválida
67+
// Verificamos que se llamó a Agent.find
68+
expect(Agent.find).toHaveBeenCalled();
2969
});
30-
try {
31-
//Validarlo
32-
await agent.validate();
33-
} catch (er) {
34-
error = er;
35-
}
36-
//Asegurarnos de que no pasa la validación
37-
//console.log(error);
38-
expect(error).not.toBeDefined();
39-
expect(error).toBeUndefined();
4070
});
4171
});

0 commit comments

Comments
 (0)