Skip to content

Commit

Permalink
feat: add getUser controller (#57)
Browse files Browse the repository at this point in the history
* feat: add getUser controller

* feat: adjust userFindById controller

* feat: add userFindById controller

* feat: add userFindById controller

* feat: add userFindById controller

* feat: add userFindById controller

* feat: create and test userFindById controller
  • Loading branch information
nathalia-84 authored May 20, 2024
1 parent fa249bc commit 6c4e188
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 5 deletions.
81 changes: 80 additions & 1 deletion src/features/user/controllers/user-controller.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,21 @@ const makeSut = () => {
}
}

class UserFindByIdServiceStub implements Service {
public execute(params: any): any {
return params;
}
}

const validator = new ValidatorStub();
const userCreateService = new UserCreateServiceStub();
const userFindByIdService = new UserFindByIdServiceStub();

const userController = new UserController(validator, userCreateService);
const userController = new UserController(
validator,
userCreateService,
userFindByIdService
);

const req = mockDeep<Request>();
const res = mockDeep<Response>();
Expand All @@ -34,6 +45,7 @@ const makeSut = () => {
res,
userController,
userCreateService,
userFindByIdService,
validator,
};
};
Expand Down Expand Up @@ -108,4 +120,71 @@ describe('[Controllers] UserController', () => {
expect(next).toHaveBeenCalledWith(error);
});
});

describe('userFindById', () => {
it('should call validator with correctly params', async () => {
const { next, req, res, userController, validator } = makeSut();

const validateSpy = vi.spyOn(validator, 'validate');

const uuid = crypto.randomUUID();

req.params = { id: uuid };
req.path = '/users';

await userController.userFindById(req, res, next);

expect(validateSpy).toHaveBeenCalledWith(expect.anything(), {
params: req.params,
path: req.path,
});
});

it('should call service with correctly params', async () => {
const { next, req, res, userController, userFindByIdService } = makeSut();

const serviceSpy = vi.spyOn(userFindByIdService, 'execute');

const uuid = crypto.randomUUID();

req.params.id = uuid;

await userController.userFindById(req, res, next);

expect(serviceSpy).toHaveBeenCalledWith({
id: req.params.id,
});
});

it('should response 404 if user is not found', async () => {
const { next, req, res, userController, userFindByIdService } = makeSut();

const serviceSpy = vi.spyOn(userFindByIdService, 'execute');

const response = undefined;

serviceSpy.mockReturnValue(response);

const uuid = crypto.randomUUID();

req.params.id = uuid;

await userController.userFindById(req, res, next);

expect(res.status).toHaveBeenCalledWith(404);
});

it('should call next when an error', async () => {
const { next, req, res, userController, userFindByIdService } = makeSut();
const error = new HttpError(500, 'error');

vi.spyOn(userFindByIdService, 'execute').mockRejectedValueOnce(
new HttpError(500, 'error')
);

await userController.userFindById(req, res, next);

expect(next).toHaveBeenCalledWith(error);
});
});
});
29 changes: 27 additions & 2 deletions src/features/user/controllers/user-controller.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { UserCreateModel } from '../models/user-create-model.js';
import { userCreateSchema } from '../validators/index.js';
import { userCreateSchema, userFindByIdSchema } from '../validators/index.js';
import type { UserFindByIdModel } from '../models/user-find-by-id-model.js';
import type { Controller } from '@/shared/protocols/controller.js';
import type { Service } from '@/shared/protocols/service.js';
import type { Validator } from '@/shared/infra/validator/validator.js';
Expand All @@ -26,8 +27,32 @@ export class UserController implements Controller {
}
};

userFindById: AsyncRequestHandler = async (req, res, next) => {
try {
this.validator.validate(userFindByIdSchema, {
params: req.params,
path: req.path,
});

const user = await this.serviceFindById.execute({
id: req.params.id,
});

if (!user) {
return res
.status(HttpStatusCode.notFound)
.json({ error: 'User not found' });
}

return res.status(HttpStatusCode.ok).json(user);
} catch (error) {
next(error);
}
};

constructor(
private validator: Validator,
private serviceCreate: Service<UserCreateModel>
private serviceCreate: Service<UserCreateModel>,
private serviceFindById: Service<UserFindByIdModel>
) {}
}
7 changes: 7 additions & 0 deletions src/features/user/models/user-find-by-id-model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { UserModel } from './user-create-model.js';

export type UserFindByIdModel = {
id: string;
};

export type UserFindByIdResponse = null | UserModel;
8 changes: 7 additions & 1 deletion src/features/user/routes/user-controller-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@ import { UserController } from '../controllers/user-controller.js';
import { UserRepository } from '../repositories/user-repository/user-repository.js';
import { UserCreateService } from '../services/user-create-service.js';
import { Validator } from '@/shared/infra/validator/validator.js';
import type { Service } from '@/shared/protocols/service.js';

export function userControllerFactory() {
const userRepository = new UserRepository();
const userServiceFindAll = new UserCreateService(userRepository);
const userServiceFindById = {} as Service;
const validator = new Validator();
const userController = new UserController(validator, userServiceFindAll);
const userController = new UserController(
validator,
userServiceFindAll,
userServiceFindById
);

return { userController };
}
3 changes: 2 additions & 1 deletion src/features/user/routes/user-routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ const router = Router();

const { userController } = userControllerFactory();
router.post('/create', userController.create);
router.get('/:id', userController.userFindById);

export default {
prefix: 'user',
prefix: 'users',
router,
};
1 change: 1 addition & 0 deletions src/features/user/validators/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './user-create-schema.js';
export * from './user-find-by-id-schema.js';
10 changes: 10 additions & 0 deletions src/features/user/validators/user-find-by-id-schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Joi from 'joi';

export const userFindByIdParamsSchema = Joi.object({
id: Joi.string().guid().required(),
});

export const userFindByIdSchema = Joi.object({
params: userFindByIdParamsSchema,
path: Joi.string().required(),
});

0 comments on commit 6c4e188

Please sign in to comment.