• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

HernanEstribou / take-home-hernan / efb9a06e-410f-4305-9ca7-9ad80eb1bade

03 Apr 2026 10:22PM UTC coverage: 81.56% (-1.0%) from 82.564%
efb9a06e-410f-4305-9ca7-9ad80eb1bade

push

circleci

HernanEstribou
feat: implement notifications feature with CRUD operations, JWT authentication, and update Swagger documentation

92 of 119 branches covered (77.31%)

Branch coverage included in aggregate %.

0 of 3 new or added lines in 3 files covered. (0.0%)

15 existing lines in 2 files now uncovered.

253 of 304 relevant lines covered (83.22%)

5.11 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.71
/src/users/users.controller.js
1
import express from 'express';
2
import Joi from 'joi';
3
import * as usersService from './users.service.js';
4
import { CreateUserDto } from './dto/create-user.dto.js';
5
import { UpdateUserDto } from './dto/update-user.dto.js';
6
import { UserResponseDto } from './dto/user-response.dto.js';
7
import { authenticate } from '../auth/auth.middleware.js';
8

9
const router = express.Router();
4✔
10

11
const idSchema = Joi.number().integer().positive().required();
4✔
12

13
// Ruta: GET /users
14
router.get('/', authenticate, async (req, res) => {
4✔
15
  try {
2✔
16
    const users = await usersService.getAllUsers();
2✔
17
    const usersDto = users.map((user) => new UserResponseDto(user));
6✔
18

19
    res.status(200).json(usersDto);
2✔
20
  } catch (error) {
UNCOV
21
    res
×
22
      .status(500)
23
      .json({ message: 'Error fetching users', error: error.message });
24
  }
25
});
26

27
// Ruta: GET /users/:id
28
router.get('/:id', authenticate, async (req, res) => {
4✔
29
  try {
10✔
30
    const { error } = idSchema.validate(req.params.id);
10✔
31
    if (error) {
10✔
32
      return res.status(400).json({ message: 'Invalid ID format' });
4✔
33
    }
34

35
    const user = await usersService.getOneUser(req.params.id);
6✔
36

37
    if (!user) {
6✔
38
      return res.status(404).json({ message: 'User not found' });
4✔
39
    }
40

41
    const userDto = new UserResponseDto(user);
2✔
42

43
    res.status(200).json(userDto);
2✔
44
  } catch (error) {
UNCOV
45
    res
×
46
      .status(500)
47
      .json({ message: 'Error fetching user', error: error.message });
48
  }
49
});
50

51
// Ruta: POST /users
52
router.post('/', async (req, res) => {
4✔
53
  const { email, password } = req.body;
6✔
54

55
  try {
6✔
56
    const userDto = new CreateUserDto({ email, password });
6✔
57

58
    const validation = userDto.validate();
6✔
59

60
    if (!validation.valid) {
6✔
61
      return res.status(400).json({
4✔
62
        message: 'Validation failed',
63
        errors: validation.errors,
64
      });
65
    }
66

67
    const user = await usersService.createNewUser(userDto);
2✔
68
    const userResponseDto = new UserResponseDto(user);
2✔
69

70
    res.status(201).json(userResponseDto);
2✔
71
  } catch (error) {
UNCOV
72
    res
×
73
      .status(500)
74
      .json({ message: 'Error creating user', error: error.message });
75
  }
76
});
77

78
// Ruta: PUT /users/:id
79
router.put('/:id', authenticate, async (req, res) => {
4✔
80
  const { email, password } = req.body;
6✔
81

82
  try {
6✔
83
    const { error } = idSchema.validate(req.params.id);
6✔
84
    if (error) {
6!
UNCOV
85
      return res.status(400).json({ message: 'Invalid ID format' });
×
86
    }
87

88
    const userDto = new UpdateUserDto({ email, password });
6✔
89

90
    const validation = userDto.validate();
6✔
91

92
    if (!validation.valid) {
6✔
93
      return res.status(400).json({
2✔
94
        message: 'Validation failed',
95
        errors: validation.errors,
96
      });
97
    }
98
    const user = await usersService.updateOneUser(req.params.id, userDto);
4✔
99

100
    if (!user) {
4✔
101
      return res.status(404).json({ message: 'User not found' });
2✔
102
    }
103

104
    if (user.id !== req.user.id) {
2!
UNCOV
105
      return res.status(403).json({ message: 'Forbidden' });
×
106
    }
107

108
    const userResponseDto = new UserResponseDto(user);
2✔
109

110
    res.status(200).json({
2✔
111
      message: 'User updated',
112
      data: userResponseDto,
113
    });
114
  } catch (error) {
UNCOV
115
    res
×
116
      .status(500)
117
      .json({ message: 'Error updating user', error: error.message });
118
  }
119
});
120

121
//Ruta: DELETE /users/:id
122
router.delete('/:id', authenticate, async (req, res) => {
4✔
123
  try {
4✔
124
    const { error } = idSchema.validate(req.params.id);
4✔
125
    if (error) {
4!
UNCOV
126
      return res.status(400).json({ message: 'Invalid ID format' });
×
127
    }
128

129
    const user = await usersService.deleteOneUser(req.params.id);
4✔
130

131
    if (!user) {
4✔
132
      return res.status(404).json({ message: 'User not found' });
2✔
133
    }
134

135
    if (user.id !== req.user.id) {
2!
UNCOV
136
      return res.status(403).json({ message: 'Forbidden' });
×
137
    }
138

139
    const userResponseDto = new UserResponseDto(user);
2✔
140

141
    res.status(200).json({
2✔
142
      message: 'User deleted',
143
      data: userResponseDto,
144
    });
145
  } catch (error) {
UNCOV
146
    res
×
147
      .status(500)
148
      .json({ message: 'Error deleting user', error: error.message });
149
  }
150
});
151

152
export default router;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc