Skip to content

Commit

Permalink
Merge pull request #45 from MatheusSanchez/edit-user
Browse files Browse the repository at this point in the history
Edit feature user and tests
  • Loading branch information
MatheusSanchez authored Feb 3, 2024
2 parents 88670e2 + 8f22a14 commit 0fa3632
Show file tree
Hide file tree
Showing 8 changed files with 255 additions and 4 deletions.
71 changes: 71 additions & 0 deletions src/controller/user/editUserById.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { afterAll, beforeAll, describe, expect, it } from 'vitest'
import request from 'supertest'
import { app } from '../../app'
import { randomUUID } from 'crypto'
import { PrismaUsersRepository } from '../../repositories/prisma/prisma-users-repository'
import { UserRepository } from '../../repositories/user-repository'

let userRepository: UserRepository

describe('edit User E2E', () => {
beforeAll(async () => {
userRepository = new PrismaUsersRepository()
await app.ready()
})

afterAll(async () => {
await app.close()
})

it('should be able to edit a user', async () => {
const email = '[email protected]'
const name = 'John'
const surname = 'Doe'
const password_hash = 'password_hash'

const newUser = await userRepository.create({
email,
name,
surname,
password_hash,
})

const editUserResponse = await request(app.server)
.put(`/user/${newUser.id}/edit`)
.send({
name: 'newName',
surname: 'surname',
country: 'country',
})

expect(editUserResponse.statusCode).toEqual(200)
expect(editUserResponse.body.user).toEqual(
expect.objectContaining({
name: 'newName',
surname: 'surname',
country: 'country',
id: newUser.id,
email,
password_hash,
}),
)
})

it('should not be able to edit a user that does not exist', async () => {
const editUserResponse = await request(app.server)
.put(`/user/${randomUUID()}/edit`)
.send({
name: 'newName',
surname: 'surname',
country: 'country',
})

expect(editUserResponse.statusCode).toEqual(404)

expect(editUserResponse.body).toEqual(
expect.objectContaining({
error: 'User was not Found !',
}),
)
})
})
41 changes: 41 additions & 0 deletions src/controller/user/editUserById.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { FastifyReply, FastifyRequest } from 'fastify'
import { z } from 'zod'
import { ResourceNotFoundError } from '../../use-cases/errors/ResourceNotFoundError'
import { PrismaUsersRepository } from '../../repositories/prisma/prisma-users-repository'
import { EditUserUseCase } from '../../use-cases/user/editUserUseCase'

export async function editUserById(
request: FastifyRequest,
response: FastifyReply,
) {
const editUserBodySchema = z.object({
name: z.string(),
surname: z.string(),
country: z.string(),
})

const editUserParamsSchema = z.object({
userId: z.string().uuid(),
})

const { name, surname, country } = editUserBodySchema.parse(request.body)
const { userId } = editUserParamsSchema.parse(request.params)

const userRepository = new PrismaUsersRepository()
const editUserUseCase = new EditUserUseCase(userRepository)

try {
const { user } = await editUserUseCase.execute({
name,
surname,
country,
userId,
})

return response.status(200).send({ user })
} catch (error) {
if (error instanceof ResourceNotFoundError) {
return response.status(404).send({ error: 'User was not Found !' })
}
}
}
3 changes: 2 additions & 1 deletion src/controller/user/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { FastifyInstance } from 'fastify'
import { getUserById } from './getUserById'
import { getUserByEmail } from './getUserByEmail'
import { registerUser } from './registerUser'
import { editUserById } from './editUserById'
import { addImageUser } from './addImageToUser'
import FastifyMultipart from '@fastify/multipart'

Expand All @@ -15,6 +16,6 @@ export async function userRoutes(app: FastifyInstance) {
app.post('/user', registerUser)
app.get('/user/:id', getUserById)
app.get('/user', getUserByEmail)

app.put('/user/:userId/edit', editUserById)
app.post('/user/:userId/photo', addImageUser)
}
21 changes: 19 additions & 2 deletions src/repositories/in-memory-db/inMemoryUserRepository.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { Prisma, User } from '@prisma/client'
import { UserRepository } from '../user-repository'
import { UserRepository, editUserRequestPrisma } from '../user-repository'
import { randomUUID } from 'crypto'

export class InMemoryUserRepository implements UserRepository {
public db: User[] = []

constructor() {}

async findByEmail(email: string): Promise<User | null> {
Expand Down Expand Up @@ -53,6 +52,24 @@ export class InMemoryUserRepository implements UserRepository {
return user
}


async edit({
name,
surname,
country,
userId,
}: editUserRequestPrisma): Promise<User> {
const indexToUpdate = this.db.findIndex((user) => user.id === userId)

this.db[indexToUpdate] = {
...this.db[indexToUpdate],
name,
surname,
country,
}

return this.db[indexToUpdate]
}
async addPhotoUrl(projectId: string, photoUrl: string): Promise<Project> {
throw new Error('Method not implemented.')
}
Expand Down
18 changes: 17 additions & 1 deletion src/repositories/prisma/prisma-users-repository.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Prisma, User } from '@prisma/client'
import { prisma } from '../../lib/prisma'
import { UserRepository } from '../user-repository'
import { UserRepository, editUserRequestPrisma } from '../user-repository'

export class PrismaUsersRepository implements UserRepository {
async findByEmail(email: string): Promise<User | null> {
Expand Down Expand Up @@ -31,6 +31,22 @@ export class PrismaUsersRepository implements UserRepository {
return user
}


async edit({
name,
surname,
country,
userId,
}: editUserRequestPrisma): Promise<User> {
const user = await prisma.user.update({
where: { id: userId },
data: { name, surname, country },
})

return user
}


async addPhotoUrl(userId: string, photoUrl: string): Promise<User> {
const user = await prisma.user.update({
where: {
Expand Down
8 changes: 8 additions & 0 deletions src/repositories/user-repository.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
import { Prisma, User } from '@prisma/client'

export interface editUserRequestPrisma {
name: string
surname: string
country: string
userId: string
}

export interface UserRepository {
create(data: Prisma.UserCreateInput): Promise<User>
findByEmail(email: string): Promise<User | null>
findById(id: string): Promise<User | null>
edit({ name, surname, country, userId }: editUserRequestPrisma): Promise<User>
addPhotoUrl(userId: string, photoUrl: string): Promise<User>
}
54 changes: 54 additions & 0 deletions src/use-cases/user/editUserUseCase.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { expect, describe, it, beforeEach } from 'vitest'

import { ResourceNotFoundError } from '../errors/ResourceNotFoundError'
import { InMemoryUserRepository } from '../../repositories/in-memory-db/inMemoryUserRepository'
import { EditUserUseCase } from './editUserUseCase'

let userRepository: InMemoryUserRepository

let editUserUseCase: EditUserUseCase

describe('Edit Project By Id Use Case', () => {
beforeEach(async () => {
userRepository = new InMemoryUserRepository()
editUserUseCase = new EditUserUseCase(userRepository)
})

it('should be able edit one user by ID', async () => {
const userToBeEdited = await userRepository.create({
name: 'John',
surname: 'Doe',
email: '[email protected]',
password_hash: '123456',
})

const { user } = await editUserUseCase.execute({
name: 'newCoolName',
surname: 'newSurCoolName',
country: 'differentCountry',
userId: userToBeEdited.id,
})

expect(user).toEqual(
expect.objectContaining({
name: 'newCoolName',
surname: 'newSurCoolName',
country: 'differentCountry',
email: '[email protected]',
password_hash: '123456',
id: userToBeEdited.id,
}),
)
})

it('should not be able to edit a user that does not exist', async () => {
await expect(() =>
editUserUseCase.execute({
name: 'newCoolName',
surname: 'newSurCoolName',
country: 'differentCountry',
userId: 'not-exist-id',
}),
).rejects.toBeInstanceOf(ResourceNotFoundError)
})
})
43 changes: 43 additions & 0 deletions src/use-cases/user/editUserUseCase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { User } from '@prisma/client'

import { ResourceNotFoundError } from '../errors/ResourceNotFoundError'
import { UserRepository } from '../../repositories/user-repository'

interface EditUserUseCaseRequest {
name: string
surname: string
country: string
userId: string
}

interface EditUserUseCaseResponse {
user: User
}

export class EditUserUseCase {
constructor(private userRepository: UserRepository) {}

async execute({
name,
surname,
country,
userId,
}: EditUserUseCaseRequest): Promise<EditUserUseCaseResponse> {
const userToBeUpdated = await this.userRepository.findById(userId)

if (!userToBeUpdated) {
throw new ResourceNotFoundError()
}

const user = await this.userRepository.edit({
name,
surname,
country,
userId,
})

return {
user,
}
}
}

0 comments on commit 0fa3632

Please sign in to comment.