Skip to content

Commit

Permalink
Merge pull request #40 from MatheusSanchez/SFD-92
Browse files Browse the repository at this point in the history
UseCase to delete projects with controller, tests and route
  • Loading branch information
pedrodecf authored Feb 2, 2024
2 parents 5006025 + 600b13e commit 9218cb1
Show file tree
Hide file tree
Showing 8 changed files with 189 additions and 0 deletions.
68 changes: 68 additions & 0 deletions src/controller/project/deleteProjectById.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { afterAll, beforeAll, describe, expect, it } from "vitest"
import request from 'supertest'
import { ProjectRepository } from '../../repositories/project-repository'
import { PrismaProjectRepository } from '../../repositories/prisma/prisma-project-repository'
import { PrismaUsersRepository } from '../../repositories/prisma/prisma-users-repository'
import { UserRepository } from '../../repositories/user-repository'
import { app } from "../../app"
import { randomUUID } from "crypto"

let projectRepository: ProjectRepository
let userRepository: UserRepository

describe('Delete Project By ID E2E', () => {
beforeAll(async () => {
projectRepository = new PrismaProjectRepository()
userRepository = new PrismaUsersRepository()

await app.ready()
})

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

it('should be able to delete a project by ID', async () => {
const description = 'ReactProject'
const link = 'www.google.com.br'
const tags = ['react', 'node']
const title = 'ReactProject'

const newUser = await userRepository.create({
email: '[email protected]',
name: 'John',
surname: 'Doe',
password_hash: 'password',
})

const project = await projectRepository.create({
description,
link,
tags,
title,
user_id: newUser.id,
})

const deletedProjectByIdResponse = await request(app.server).delete(
`/project/${project.id}`,
)

expect(deletedProjectByIdResponse.statusCode).toEqual(200)
expect(deletedProjectByIdResponse.body).toEqual({})
})

it('should not be able to delete a project by ID that does not exist', async () => {

const deletedProjectByIdResponse = await request(app.server).delete(
`/project/${randomUUID()}`,
)

expect(deletedProjectByIdResponse.statusCode).toEqual(404)
expect(deletedProjectByIdResponse.body).toEqual(
expect.objectContaining({
error: 'Unable to delete project !',
}),
)
})

})
25 changes: 25 additions & 0 deletions src/controller/project/deleteProjectById.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { FastifyReply, FastifyRequest } from "fastify"
import { PrismaProjectRepository } from "../../repositories/prisma/prisma-project-repository"
import { DeleteProjectByIdUseCase } from "../../use-cases/project/deleteProjectByIdUseCase"
import { z } from "zod"

export async function deleteProjectById(
request: FastifyRequest,
response: FastifyReply,
) {
const projectRepository = new PrismaProjectRepository()
const deleteProjectByIdUseCase = new DeleteProjectByIdUseCase(projectRepository)

const DeleteProjectByIdParamsSchema = z.object({
projectId: z.string().uuid(),
})

const { projectId } = DeleteProjectByIdParamsSchema.parse(request.params)

try {
await deleteProjectByIdUseCase.execute({ projectId })
return response.status(200).send()
} catch (error) {
return response.status(404).send({ error: 'Unable to delete project !'})
}
}
2 changes: 2 additions & 0 deletions src/controller/project/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import path from 'path'
import fastifyStatic from '@fastify/static'
import { getProjectsByTags } from './getProjectsByTags'
import { editProject } from './editProjectById'
import { deleteProjectById } from './deleteProjectById'

export async function projectRoutes(app: FastifyInstance) {
app.register(FastifyMultipart, {
Expand All @@ -30,4 +31,5 @@ export async function projectRoutes(app: FastifyInstance) {
app.post('/user/:userId/project', createProject)

app.put('/project/:projectId/edit', editProject)
app.delete('/project/:projectId', deleteProjectById)
}
10 changes: 10 additions & 0 deletions src/repositories/in-memory-db/inMemoryProjectRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,16 @@ export class InMemoryProjectRepository implements ProjectRepository {
async addPhotoUrl(projectId: string, photoUrl: string): Promise<Project> {
throw new Error('Method not implemented.')
}

async deleteProjectByID(projectId: string): Promise<void> {
const index = this.dbProject.findIndex((project) => project.id === projectId);

if (index !== -1) {
this.dbProject.splice(index, 1);
}

return
}

async fetchProjectByTags(tags: string[]): Promise<Project[]> {
const projects = this.dbProject.filter((project) =>
Expand Down
10 changes: 10 additions & 0 deletions src/repositories/prisma/prisma-project-repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ export class PrismaProjectRepository implements ProjectRepository {
return project
}

async deleteProjectByID(projectId: string):Promise<void> {
await prisma.project.delete({
where: {
id: projectId
}
})

return
}


async edit(data: Prisma.ProjectUncheckedCreateInput): Promise<Project> {
const project = await prisma.project.update({
Expand Down
1 change: 1 addition & 0 deletions src/repositories/project-repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ export interface ProjectRepository {
addPhotoUrl(projectId: string, photoUrl: string): Promise<Project>
fetchProjectByTags(tags: string[]): Promise<Project[]>
edit(data: Prisma.ProjectUncheckedCreateInput): Promise<Project>
deleteProjectByID(projectID: string): Promise<void>
}
55 changes: 55 additions & 0 deletions src/use-cases/project/deleteProjectByIdUseCase.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { describe, expect, it, beforeEach } from "vitest";
import { ProjectRepository } from "../../repositories/project-repository";
import { DeleteProjectByIdUseCase } from "./deleteProjectByIdUseCase";
import { InMemoryProjectRepository } from "../../repositories/in-memory-db/inMemoryProjectRepository";
import { GetProjectsByUserIdUseCase } from "./getProjectsByUserIdUseCase";
import { UserRepository } from "../../repositories/user-repository";
import { InMemoryUserRepository } from "../../repositories/in-memory-db/inMemoryUserRepository";

let userRepository: UserRepository
let projectRepository: ProjectRepository
let deleteProjectByIdUseCase: DeleteProjectByIdUseCase
let getProjectsByUserIdUseCase: GetProjectsByUserIdUseCase

describe('Delete Project By Id Use Case', () => {
beforeEach(() => {
userRepository = new InMemoryUserRepository()
projectRepository = new InMemoryProjectRepository()
deleteProjectByIdUseCase = new DeleteProjectByIdUseCase(projectRepository)
getProjectsByUserIdUseCase = new GetProjectsByUserIdUseCase(
projectRepository,
userRepository,
)
})

it('should be able delete project by ID', async () => {
const newUser = await userRepository.create({
name: 'Matheus',
surname: 'Sanchez',
email: '[email protected]',
password_hash: '123456',
})

const firstProject = await projectRepository.create({
title: 'React Typescript 1',
description: 'Best Project',
tags: ['react', 'node'],
link: 'https://github.com/luiseduardo3/nodets-petcanil',
user_id: newUser.id,
})

const secondProject = await projectRepository.create({
title: 'React Typescript 2',
description: 'Best Project 2',
tags: ['react', 'figma'],
link: 'https://www.linkedin.com/in/pedrodecf/',
user_id: newUser.id,
})

const deletedProject = await deleteProjectByIdUseCase.execute({ projectId: firstProject.id })
const { projects } = await getProjectsByUserIdUseCase.execute({ userId: newUser.id })

expect(deletedProject).toEqual(undefined)
expect(projects).toHaveLength(1)
})
})
18 changes: 18 additions & 0 deletions src/use-cases/project/deleteProjectByIdUseCase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { ProjectRepository } from "../../repositories/project-repository";

interface DeleteProjectByIdRequest {
projectId: string
}

export class DeleteProjectByIdUseCase{
constructor (
private projectRepository: ProjectRepository,
) {}

async execute({
projectId,
}: DeleteProjectByIdRequest): Promise<void>{
await this.projectRepository.deleteProjectByID(projectId)
return
}
}

0 comments on commit 9218cb1

Please sign in to comment.