Skip to content

Commit f849ebd

Browse files
authored
[IMPROVEMENT] Add more test cases for BE (#30)
* Refactor frontend * Add more test cases * Fix dashboard component test
1 parent e5bec50 commit f849ebd

18 files changed

+296
-465
lines changed
+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
const request = require('supertest');
2+
const mongoose = require('mongoose');
3+
const { MongoMemoryServer } = require('mongodb-memory-server');
4+
const express = require('express');
5+
const bodyParser = require('body-parser');
6+
const jwt = require('jsonwebtoken');
7+
const { createUser, getAllUsers, updateUser, deleteUser } = require('../controllers/adminController');
8+
const { auth, adminOnly } = require('../middlewares/auth');
9+
const User = require('../models/User');
10+
11+
const JWT_SECRET = 'test_secret';
12+
13+
const app = express();
14+
app.use(bodyParser.json());
15+
16+
// Mock environment variables
17+
process.env.JWT_SECRET = JWT_SECRET;
18+
process.env.ADMIN_EMAIL = '[email protected]';
19+
20+
// Setup routes with middlewares
21+
app.post('/users', auth, adminOnly, createUser);
22+
app.get('/users', auth, adminOnly, getAllUsers);
23+
app.put('/users/:id', auth, adminOnly, updateUser);
24+
app.delete('/users/:id', auth, adminOnly, deleteUser);
25+
26+
describe('User Controller with Auth Middleware', () => {
27+
let mongoServer;
28+
let userToken;
29+
let adminToken;
30+
31+
beforeAll(async () => {
32+
mongoServer = await MongoMemoryServer.create();
33+
await mongoose.connect(mongoServer.getUri(), {});
34+
35+
// Create a regular user and an admin user
36+
const user = new User({ email: '[email protected]', password: 'password123', isAdmin: false });
37+
const admin = new User({ email: '[email protected]', password: 'password123', isAdmin: true });
38+
39+
await user.save();
40+
await admin.save();
41+
42+
// Generate tokens
43+
userToken = jwt.sign({ email: user.email, isAdmin: user.isAdmin }, process.env.JWT_SECRET);
44+
adminToken = jwt.sign({ email: admin.email, isAdmin: admin.isAdmin }, process.env.JWT_SECRET);
45+
});
46+
47+
afterAll(async () => {
48+
await mongoose.disconnect();
49+
await mongoServer.stop();
50+
});
51+
52+
afterEach(async () => {
53+
await User.deleteMany({});
54+
});
55+
56+
describe('Protected Routes', () => {
57+
it('should deny access if no token is provided', async () => {
58+
const res = await request(app).get('/users');
59+
expect(res.statusCode).toBe(401);
60+
expect(res.body).toHaveProperty('message', 'Access denied. No token provided.');
61+
});
62+
63+
it('should deny access if an invalid token is provided', async () => {
64+
const res = await request(app)
65+
.get('/users')
66+
.set('Authorization', `Bearer invalidtoken`);
67+
68+
expect(res.statusCode).toBe(400);
69+
expect(res.body).toHaveProperty('message');
70+
});
71+
72+
it('should deny access to non-admin users', async () => {
73+
const res = await request(app)
74+
.get('/users')
75+
.set('Authorization', `Bearer ${userToken}`);
76+
77+
expect(res.statusCode).toBe(403);
78+
expect(res.body).toHaveProperty('message', 'Access denied. Admins only.');
79+
});
80+
81+
it('should allow access to admin users', async () => {
82+
const res = await request(app)
83+
.get('/users')
84+
.set('Authorization', `Bearer ${adminToken}`);
85+
86+
expect(res.statusCode).toBe(200);
87+
});
88+
89+
it('should create a new user when an admin user is authenticated', async () => {
90+
const res = await request(app)
91+
.post('/users')
92+
.set('Authorization', `Bearer ${adminToken}`)
93+
.send({ email: '[email protected]', password: 'password123', isAdmin: false });
94+
95+
expect(res.statusCode).toBe(201);
96+
expect(res.body).toHaveProperty('_id');
97+
expect(res.body.email).toBe('[email protected]');
98+
});
99+
100+
it('should not create a new user when a non-admin user is authenticated', async () => {
101+
const res = await request(app)
102+
.post('/users')
103+
.set('Authorization', `Bearer ${userToken}`)
104+
.send({ email: '[email protected]', password: 'password123', isAdmin: false });
105+
106+
expect(res.statusCode).toBe(403);
107+
expect(res.body).toHaveProperty('message', 'Access denied. Admins only.');
108+
});
109+
});
110+
});

backend/__tests__/defectConfigsController.test.js

+58-25
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,31 @@ const request = require('supertest');
22
const express = require('express');
33
const mongoose = require('mongoose');
44
const { MongoMemoryServer } = require('mongodb-memory-server');
5+
const jwt = require('jsonwebtoken');
56
const DefectConfigModel = require('../models/DefectConfigModel');
6-
const defectConfigRoutes = require('../routes/defectConfigRoutes');
7+
const { getDefectConfig, updateDefectConfig } = require('../controllers/defectConfigsController');
8+
const { auth } = require('../middlewares/auth');
79

810
// Set up an Express app for testing
911
const app = express();
1012
app.use(express.json());
11-
app.use('/defect-config', defectConfigRoutes);
13+
14+
// Apply auth middleware
15+
app.get('/defect-config', auth, getDefectConfig);
16+
app.post('/defect-config', auth, updateDefectConfig);
17+
18+
const JWT_SECRET = 'test_secret';
1219

1320
let mongoServer;
21+
let userToken;
1422

1523
beforeAll(async () => {
1624
mongoServer = await MongoMemoryServer.create();
1725
const uri = mongoServer.getUri();
18-
await mongoose.connect(uri, { useNewUrlParser: true, useUnifiedTopology: true });
26+
await mongoose.connect(uri, {});
27+
process.env.JWT_SECRET = JWT_SECRET;
28+
// Generate a mock token for a regular user
29+
userToken = jwt.sign({ email: '[email protected]', isAdmin: false }, process.env.JWT_SECRET);
1930
});
2031

2132
afterAll(async () => {
@@ -41,64 +52,86 @@ beforeEach(async () => {
4152

4253
describe('Defect Config Endpoints', () => {
4354
describe('GET /defect-config', () => {
44-
it('should return the defect configuration', async () => {
55+
it('should return 401 if no token is provided', async () => {
4556
const res = await request(app).get('/defect-config');
57+
expect(res.statusCode).toBe(401);
58+
expect(res.body.message).toBe('Access denied. No token provided.');
59+
});
60+
61+
it('should return 200 and the defect config if token is valid', async () => {
62+
const res = await request(app)
63+
.get('/defect-config')
64+
.set('Authorization', `Bearer ${userToken}`);
4665

4766
expect(res.statusCode).toBe(200);
48-
expect(res.body).toHaveProperty('greening', 0.1);
49-
expect(res.body).toHaveProperty('dryRot', 0.2);
50-
expect(res.body).toHaveProperty('wetRot', 0.3);
51-
expect(res.body).toHaveProperty('wireWorm', 0.4);
52-
expect(res.body).toHaveProperty('malformed', 0.5);
53-
expect(res.body).toHaveProperty('growthCrack', 0.6);
54-
expect(res.body).toHaveProperty('mechanicalDamage', 0.7);
55-
expect(res.body).toHaveProperty('dirtClod', 0.8);
56-
expect(res.body).toHaveProperty('stone', 0.9);
67+
expect(res.body).toEqual(expect.objectContaining({
68+
greening: 0.1,
69+
dryRot: 0.2,
70+
wetRot: 0.3,
71+
wireWorm: 0.4,
72+
malformed: 0.5,
73+
growthCrack: 0.6,
74+
mechanicalDamage: 0.7,
75+
dirtClod: 0.8,
76+
stone: 0.9,
77+
}));
5778
});
5879
});
5980

6081
describe('POST /defect-config', () => {
61-
it('should update the defect configuration successfully', async () => {
82+
it('should return 401 if no token is provided', async () => {
83+
const res = await request(app)
84+
.post('/defect-config')
85+
.send({ greening: 0.15 });
86+
87+
expect(res.statusCode).toBe(401);
88+
expect(res.body.message).toBe('Access denied. No token provided.');
89+
});
90+
91+
it('should update the defect config if token is valid', async () => {
6292
const updateData = {
6393
greening: 0.15,
6494
dryRot: 0.25,
65-
wetRot: 0.35,
6695
};
6796

6897
const res = await request(app)
6998
.post('/defect-config')
99+
.set('Authorization', `Bearer ${userToken}`)
70100
.send(updateData);
71101

72102
expect(res.statusCode).toBe(200);
73103
expect(res.body.message).toBe('Defect configuration updated successfully');
74-
expect(res.body.data.greening).toBe(0.15);
75-
expect(res.body.data.dryRot).toBe(0.25);
76-
expect(res.body.data.wetRot).toBe(0.35);
104+
expect(res.body.data).toEqual(expect.objectContaining(updateData));
105+
106+
const updatedConfig = await DefectConfigModel.findOne();
107+
expect(updatedConfig.greening).toBe(0.15);
108+
expect(updatedConfig.dryRot).toBe(0.25);
77109
});
78110

79-
it('should return 404 if no defect configuration exists', async () => {
111+
it('should return 404 if defect config not found', async () => {
80112
await DefectConfigModel.deleteMany({});
81113

82114
const res = await request(app)
83115
.post('/defect-config')
116+
.set('Authorization', `Bearer ${userToken}`)
84117
.send({ greening: 0.15 });
85118

86119
expect(res.statusCode).toBe(404);
87120
expect(res.body.message).toBe('Defect configuration not found');
88121
});
89122

90-
it('should return 500 if validation fails', async () => {
91-
const invalidUpdateData = {
92-
greening: 1.5, // Invalid: exceeds max value of 1
93-
};
123+
it('should handle errors during update', async () => {
124+
jest.spyOn(DefectConfigModel.prototype, 'save').mockImplementationOnce(() => {
125+
throw new Error('Database error');
126+
});
94127

95128
const res = await request(app)
96129
.post('/defect-config')
97-
.send(invalidUpdateData);
130+
.set('Authorization', `Bearer ${userToken}`)
131+
.send({ greening: 0.15 });
98132

99133
expect(res.statusCode).toBe(500);
100134
expect(res.body.message).toBe('Error updating defect configuration');
101-
expect(res.body.error).toContain('validation failed');
102135
});
103136
});
104137
});

0 commit comments

Comments
 (0)