Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get project by ID - Controller and Use Case #28

Merged
merged 4 commits into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/controller/project/createProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,20 @@ export async function createProject(
userRepository,
)
try {
await createProjectUseCase.execute({
const project = await createProjectUseCase.execute({
userId,
title,
tags,
link,
description,
})

return response.status(201).send({ project })
} catch (error) {
if (error instanceof ResourceNotFoundError) {
return response.status(404).send({ message: error.message })
return response.status(404).send({ message: 'User was not Found !' })
}

throw error
}

return response.status(201).send()
}
74 changes: 74 additions & 0 deletions src/controller/project/getProjectById.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { afterAll, beforeAll, describe, expect, it } from 'vitest'
import request from 'supertest'
import { app } from '../../app'
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 { randomUUID } from 'crypto'

let projectRepository: ProjectRepository
let userRepository: UserRepository

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

await app.ready()
})

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

it('should be able to get a project by ID', async () => {
const description = 'ReactProject'
const link = 'www.google.com.br'
const tags = 'React'
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 getProjectByIdResponse = await request(app.server).get(
`/project/${project.id}`,
)

expect(getProjectByIdResponse.statusCode).toEqual(200)
expect(getProjectByIdResponse.body.project).toEqual(
expect.objectContaining({ title }),
)

expect(getProjectByIdResponse.body.project).toEqual(
expect.objectContaining({ tags }),
)
})

it('should not be able to get a project that does not exist', async () => {
const getProjectByIdResponse = await request(app.server).get(
`/project/${randomUUID()}`,
)

expect(getProjectByIdResponse.statusCode).toEqual(404)

expect(getProjectByIdResponse.body).toEqual(
expect.objectContaining({
error: 'Project was not Found !',
}),
)
})
})
28 changes: 28 additions & 0 deletions src/controller/project/getProjectById.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { FastifyReply, FastifyRequest } from 'fastify'
import { z } from 'zod'
import { PrismaProjectRepository } from '../../repositories/prisma/prisma-project-repository'
import { ResourceNotFoundError } from '../../use-cases/errors/ResourceNotFoundError'
import { GetProjectsByIdUseCase } from '../../use-cases/getProjectsByIdUseCase'

export async function getProjectsById(
request: FastifyRequest,
response: FastifyReply,
) {
const projectRepository = new PrismaProjectRepository()
const getProjectsByIdUseCase = new GetProjectsByIdUseCase(projectRepository)

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

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

try {
const { project } = await getProjectsByIdUseCase.execute({ projectId })
return response.status(200).send({ project })
} catch (error) {
if (error instanceof ResourceNotFoundError) {
return response.status(404).send({ error: 'Project was not Found !' })
}
}
}
4 changes: 2 additions & 2 deletions src/controller/project/getProjectsByUserId.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ describe('Get Projets By UserId E2E', () => {
})

const getProjectsByUserIdResponse = await request(app.server).get(
`/project/${newUser.id}`,
`/projects/${newUser.id}`,
)

expect(getProjectsByUserIdResponse.statusCode).toEqual(200)
Expand All @@ -70,7 +70,7 @@ describe('Get Projets By UserId E2E', () => {

it('should not be able to project that user does not exist', async () => {
const getProjectsByUserIdResponse = await request(app.server).get(
`/project/${randomUUID()}`,
`/projects/${randomUUID()}`,
)

expect(getProjectsByUserIdResponse.statusCode).toEqual(404)
Expand Down
4 changes: 3 additions & 1 deletion src/controller/project/routes.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { FastifyInstance } from 'fastify'
import { createProject } from './createProject'
import { getProjectsByUserId } from './getProjectsByUserId'
import { getProjectsById } from './getProjectById'

export async function projectRoutes(app: FastifyInstance) {
app.get('/project/:userId', getProjectsByUserId)
app.get('/projects/:userId', getProjectsByUserId)
app.get('/project/:projectId', getProjectsById)
app.post('/user/:userId/project', createProject)
}
8 changes: 8 additions & 0 deletions src/repositories/in-memory-db/inMemoryProjectRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,12 @@ export class InMemoryProjectRepository implements ProjectRepository {

return projects
}

async fetchProjectById(projectId: string): Promise<Project | null> {
const project = this.dbProject.find((project) => project.id === projectId)
if (!project) {
return null
}
return project
}
}
9 changes: 9 additions & 0 deletions src/repositories/prisma/prisma-project-repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,13 @@ export class PrismaProjectRepository implements ProjectRepository {
return projects
}

async fetchProjectById(projectId: string): Promise<Project | null> {
const project = await prisma.project.findUnique({
where: {
id: projectId,
},
})

return project
}
}
1 change: 1 addition & 0 deletions src/repositories/project-repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ import { Prisma, Project } from '@prisma/client'
export interface ProjectRepository {
create(data: Prisma.ProjectUncheckedCreateInput): Promise<Project>
fetchProjectsByUserId(userId: string): Promise<Project[]>
fetchProjectById(projectId: string): Promise<Project | null>
}
45 changes: 45 additions & 0 deletions src/use-cases/getProjectsByIdUseCase.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { expect, describe, it, beforeEach } from 'vitest'

import { InMemoryProjectRepository } from '../repositories/in-memory-db/inMemoryProjectRepository'
import { ProjectRepository } from '../repositories/project-repository'
import { ResourceNotFoundError } from './errors/ResourceNotFoundError'
import { GetProjectsByIdUseCase } from './getProjectsByIdUseCase'

let projectRepository: ProjectRepository
let getProjectByIdUseCase: GetProjectsByIdUseCase

describe('Get Project By Id Use Case', () => {
beforeEach(() => {
projectRepository = new InMemoryProjectRepository()
getProjectByIdUseCase = new GetProjectsByIdUseCase(projectRepository)
})

it('should be able get project by ID', async () => {
const newProject = await projectRepository.create({
title: 'React Typescript 1',
description: 'Best Project',
tags: 'React',
link: 'https://github.com/luiseduardo3/nodets-petcanil',
user_id: 'user_id',
})

const { project } = await getProjectByIdUseCase.execute({
projectId: newProject.id,
})

expect(project).toEqual(
expect.objectContaining({
title: 'React Typescript 1',
id: newProject.id,
}),
)
})

it('should not be able to get a project that does not exist', async () => {
await expect(() =>
getProjectByIdUseCase.execute({
projectId: 'projectDoesNotExist',
}),
).rejects.toBeInstanceOf(ResourceNotFoundError)
})
})
31 changes: 31 additions & 0 deletions src/use-cases/getProjectsByIdUseCase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Project } from '@prisma/client'

import { ProjectRepository } from '../repositories/project-repository'

import { ResourceNotFoundError } from './errors/ResourceNotFoundError'

interface GetProjectByIdRequest {
projectId: string
}

interface GetProjectByIdResponse {
project: Project
}

export class GetProjectsByIdUseCase {
constructor(private projectRepository: ProjectRepository) {}

async execute({
projectId,
}: GetProjectByIdRequest): Promise<GetProjectByIdResponse> {
const project = await this.projectRepository.fetchProjectById(projectId)

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

return {
project,
}
}
}
Loading