Skip to content

Commit

Permalink
Feat(Module, Routes): Implement get module details route
Browse files Browse the repository at this point in the history
  • Loading branch information
Artur-Poffo committed Feb 25, 2024
1 parent 4f76f30 commit fc18648
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { ResourceNotFoundError } from '@/core/errors/errors/resource-not-found-error'
import { makeModule } from '../../../../../test/factories/make-module'
import { InMemoryClassesRepository } from '../../../../../test/repositories/in-memory-classes-repository'
import { InMemoryModulesRepository } from '../../../../../test/repositories/in-memory-modules-repository'
import { GetModuleDetailsUseCase } from './get-module-details'

let inMemoryClassesRepository: InMemoryClassesRepository
let inMemoryModulesRepository: InMemoryModulesRepository
let sut: GetModuleDetailsUseCase

describe('Get module details use case', () => {
beforeEach(() => {
inMemoryClassesRepository = new InMemoryClassesRepository()
inMemoryModulesRepository = new InMemoryModulesRepository(inMemoryClassesRepository)

sut = new GetModuleDetailsUseCase(inMemoryModulesRepository)
})

it('should be able to get module details', async () => {
const module = makeModule({ name: 'John Doe Module' })
await inMemoryModulesRepository.create(module)

const result = await sut.exec({
moduleId: module.id.toString()
})

expect(result.isRight()).toBe(true)
expect(result.value).toMatchObject({
module: expect.objectContaining({
name: 'John Doe Module'
})
})
})

it('should not be able to get module details of a inexistent module', async () => {
const result = await sut.exec({
moduleId: 'inexistentCourseId'
})

expect(result.isLeft()).toBe(true)
expect(result.value).toBeInstanceOf(ResourceNotFoundError)
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { left, right, type Either } from '@/core/either'
import { ResourceNotFoundError } from '@/core/errors/errors/resource-not-found-error'
import { type UseCase } from '@/core/use-cases/use-case'
import { type Module } from '../../enterprise/entities/module'
import { type ModulesRepository } from '../repositories/modules-repository'

interface GetModuleDetailsUseCaseRequest {
moduleId: string
}

type GetModuleDetailsUseCaseResponse = Either<
ResourceNotFoundError,
{
module: Module
}
>

export class GetModuleDetailsUseCase implements UseCase<GetModuleDetailsUseCaseRequest, GetModuleDetailsUseCaseResponse> {
constructor(
private readonly modulesRepository: ModulesRepository
) { }

async exec({
moduleId
}: GetModuleDetailsUseCaseRequest): Promise<GetModuleDetailsUseCaseResponse> {
const module = await this.modulesRepository.findById(moduleId)

if (!module) {
return left(new ResourceNotFoundError())
}

return right({
module
})
}
}
38 changes: 38 additions & 0 deletions src/infra/http/controllers/get-module-details.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { ResourceNotFoundError } from '@/core/errors/errors/resource-not-found-error'
import { makeModuleMapper } from '@/infra/database/prisma/mappers/factories/make-module-mapper'
import { makeGetModuleDetailsUseCase } from '@/infra/use-cases/factories/make-get-module-details-use-case'
import { type FastifyReply, type FastifyRequest } from 'fastify'
import { z } from 'zod'
import { ModulePresenter } from '../presenters/module-presenter'

const getModuleDetailsParamsSchema = z.object({
moduleId: z.string().uuid()
})

export async function getModuleDetailsController(request: FastifyRequest, reply: FastifyReply) {
const { moduleId } = getModuleDetailsParamsSchema.parse(request.params)

const getModuleDetailsUseCase = makeGetModuleDetailsUseCase()

const result = await getModuleDetailsUseCase.exec({
moduleId
})

if (result.isLeft()) {
const error = result.value

switch (error.constructor) {
case ResourceNotFoundError:
return await reply.status(404).send({ message: error.message })
default:
return await reply.status(500).send({ message: error.message })
}
}

const moduleMapper = makeModuleMapper()
const module = await moduleMapper.toPrisma(result.value.module)

return await reply.status(200).send({
module: ModulePresenter.toHTTP(module)
})
}
2 changes: 2 additions & 0 deletions src/infra/http/routes/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import { deleteModuleController } from '../controllers/delete-module'
import { editModuleDetailsController } from '../controllers/edit-module-details'
import { fetchCourseModulesController } from '../controllers/fetch-course-modules'
import { fetchModuleClassesController } from '../controllers/fetch-module-classes'
import { getModuleDetailsController } from '../controllers/get-module-details'
import { registerModuleToCourseController } from '../controllers/register-module-to-course'
import { verifyJwt } from '../middlewares/verify-jwt'
import { verifyUserRole } from '../middlewares/verify-user-role'

export async function moduleRoutes(app: FastifyInstance) {
app.get('/modules/:moduleId', { onRequest: [verifyJwt] }, getModuleDetailsController)
app.get('/courses/:courseId/modules', { onRequest: [verifyJwt] }, fetchCourseModulesController)
app.get('/modules/:moduleId/classes', { onRequest: [verifyJwt] }, fetchModuleClassesController)

Expand Down
12 changes: 12 additions & 0 deletions src/infra/use-cases/factories/make-get-module-details-use-case.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { GetModuleDetailsUseCase } from '@/domain/course-management/application/use-cases/get-module-details'
import { makePrismaModulesRepository } from '@/infra/database/prisma/repositories/factories/make-prisma-modules-repository'

export function makeGetModuleDetailsUseCase() {
const prismaModulesRepository = makePrismaModulesRepository()

const getModuleDetailsUseCase = new GetModuleDetailsUseCase(
prismaModulesRepository
)

return getModuleDetailsUseCase
}

0 comments on commit fc18648

Please sign in to comment.