-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feat(Class, Enrollment, Route): Fetch enrollment completed classes route
- Loading branch information
1 parent
a079985
commit 786f328
Showing
25 changed files
with
495 additions
and
65 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
src/domain/course-management/application/use-cases/errors/item-already-completed-error.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { type UseCaseError } from '@/core/errors/use-case-error' | ||
|
||
export class ItemAlreadyCompletedError extends Error implements UseCaseError { | ||
constructor() { | ||
super('Item already marked as completed.') | ||
} | ||
} |
113 changes: 113 additions & 0 deletions
113
...domain/course-management/application/use-cases/fetch-enrollment-completed-classes.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
import { ResourceNotFoundError } from '@/core/errors/errors/resource-not-found-error' | ||
import { makeClass } from '../../../../../test/factories/make-class' | ||
import { makeCourse } from '../../../../../test/factories/make-course' | ||
import { makeEnrollment } from '../../../../../test/factories/make-enrollment' | ||
import { makeEnrollmentCompletedItem } from '../../../../../test/factories/make-enrollment-completed-item' | ||
import { makeInstructor } from '../../../../../test/factories/make-instructor' | ||
import { makeModule } from '../../../../../test/factories/make-module' | ||
import { makeStudent } from '../../../../../test/factories/make-student' | ||
import { InMemoryClassesRepository } from '../../../../../test/repositories/in-memory-classes-repository' | ||
import { InMemoryCourseTagsRepository } from '../../../../../test/repositories/in-memory-course-tags-repository' | ||
import { InMemoryCoursesRepository } from '../../../../../test/repositories/in-memory-courses-repository' | ||
import { InMemoryEnrollmentCompletedItemsRepository } from '../../../../../test/repositories/in-memory-enrollment-completed-items-repository' | ||
import { InMemoryEnrollmentsRepository } from '../../../../../test/repositories/in-memory-enrollments-repository' | ||
import { InMemoryStudentsRepository } from '../../../../../test/repositories/in-memory-students-repository' | ||
import { InMemoryInstructorRepository } from './../../../../../test/repositories/in-memory-instructors-repository' | ||
import { InMemoryModulesRepository } from './../../../../../test/repositories/in-memory-modules-repository' | ||
import { FetchEnrollmentCompletedClassesUseCase } from './fetch-enrollment-completed-classes' | ||
|
||
let inMemoryEnrollmentCompletedItemsRepository: InMemoryEnrollmentCompletedItemsRepository | ||
let inMemoryEnrollmentsRepository: InMemoryEnrollmentsRepository | ||
let inMemoryCourseTagsRepository: InMemoryCourseTagsRepository | ||
let inMemoryStudentsRepository: InMemoryStudentsRepository | ||
let inMemoryClassesRepository: InMemoryClassesRepository | ||
let inMemoryInstructorsRepository: InMemoryInstructorRepository | ||
let inMemoryModulesRepository: InMemoryModulesRepository | ||
let inMemoryCoursesRepository: InMemoryCoursesRepository | ||
let sut: FetchEnrollmentCompletedClassesUseCase | ||
|
||
describe('Fetch enrollment completed classes use case', () => { | ||
beforeEach(() => { | ||
inMemoryStudentsRepository = new InMemoryStudentsRepository() | ||
inMemoryEnrollmentCompletedItemsRepository = new InMemoryEnrollmentCompletedItemsRepository() | ||
inMemoryCourseTagsRepository = new InMemoryCourseTagsRepository() | ||
inMemoryClassesRepository = new InMemoryClassesRepository() | ||
inMemoryInstructorsRepository = new InMemoryInstructorRepository() | ||
|
||
inMemoryModulesRepository = new InMemoryModulesRepository(inMemoryClassesRepository) | ||
|
||
inMemoryEnrollmentsRepository = new InMemoryEnrollmentsRepository( | ||
inMemoryStudentsRepository, inMemoryEnrollmentCompletedItemsRepository | ||
) | ||
inMemoryCoursesRepository = new InMemoryCoursesRepository( | ||
inMemoryModulesRepository, inMemoryInstructorsRepository, inMemoryEnrollmentsRepository, inMemoryStudentsRepository, inMemoryCourseTagsRepository | ||
) | ||
|
||
sut = new FetchEnrollmentCompletedClassesUseCase( | ||
inMemoryEnrollmentsRepository, | ||
inMemoryEnrollmentCompletedItemsRepository | ||
) | ||
}) | ||
|
||
it('should be able to fetch enrollment completed classes', async () => { | ||
const instructor = makeInstructor() | ||
await inMemoryInstructorsRepository.create(instructor) | ||
|
||
const course = makeCourse({ instructorId: instructor.id }) | ||
await inMemoryCoursesRepository.create(course) | ||
|
||
const module = makeModule({ | ||
courseId: course.id, | ||
moduleNumber: 1 | ||
}) | ||
await inMemoryModulesRepository.create(module) | ||
|
||
const firstClassToMarkAsCompleted = makeClass({ name: 'John Doe Class 1', moduleId: module.id, classNumber: 1 }) | ||
const secondClassToMarkAsCompleted = makeClass({ name: 'John Doe Class 2', moduleId: module.id, classNumber: 2 }) | ||
|
||
await Promise.all([ | ||
inMemoryClassesRepository.create(firstClassToMarkAsCompleted), | ||
inMemoryClassesRepository.create(secondClassToMarkAsCompleted) | ||
]) | ||
|
||
const student = makeStudent() | ||
await inMemoryStudentsRepository.create(student) | ||
|
||
const enrollment = makeEnrollment({ studentId: student.id, courseId: course.id }) | ||
await inMemoryEnrollmentsRepository.create(enrollment) | ||
|
||
const firstCompletedItem = makeEnrollmentCompletedItem({ itemId: firstClassToMarkAsCompleted.id, enrollmentId: enrollment.id, type: 'CLASS' }) | ||
const secondCompletedItem = makeEnrollmentCompletedItem({ itemId: secondClassToMarkAsCompleted.id, enrollmentId: enrollment.id, type: 'CLASS' }) | ||
|
||
await Promise.all([ | ||
inMemoryEnrollmentCompletedItemsRepository.create(firstCompletedItem), | ||
inMemoryEnrollmentCompletedItemsRepository.create(secondCompletedItem) | ||
]) | ||
|
||
const result = await sut.exec({ | ||
enrollmentId: enrollment.id.toString() | ||
}) | ||
|
||
expect(result.isRight()).toBe(true) | ||
expect(result.value).toMatchObject({ | ||
completedClasses: expect.arrayContaining([ | ||
expect.objectContaining({ | ||
itemId: firstCompletedItem.itemId | ||
}), | ||
expect.objectContaining({ | ||
itemId: secondCompletedItem.itemId | ||
}) | ||
]) | ||
}) | ||
expect(inMemoryEnrollmentCompletedItemsRepository.items).toHaveLength(2) | ||
}) | ||
|
||
it('should not be able to fetch enrollment completed classes from a inexistent enrollment', async () => { | ||
const result = await sut.exec({ | ||
enrollmentId: 'inexistentEnrollmentId' | ||
}) | ||
|
||
expect(result.isLeft()).toBe(true) | ||
expect(result.value).toBeInstanceOf(ResourceNotFoundError) | ||
}) | ||
}) |
42 changes: 42 additions & 0 deletions
42
src/domain/course-management/application/use-cases/fetch-enrollment-completed-classes.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
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 EnrollmentCompletedItem } from '../../enterprise/entities/enrollment-completed-item' | ||
import { type EnrollmentCompletedItemsRepository } from '../repositories/enrollment-completed-items-repository' | ||
import { type EnrollmentsRepository } from '../repositories/enrollments-repository' | ||
|
||
interface FetchEnrollmentCompletedClassesUseCaseRequest { | ||
enrollmentId: string | ||
} | ||
|
||
type FetchEnrollmentCompletedClassesUseCaseResponse = Either< | ||
ResourceNotFoundError, | ||
{ | ||
completedClasses: EnrollmentCompletedItem[] | ||
} | ||
> | ||
|
||
export class FetchEnrollmentCompletedClassesUseCase implements UseCase<FetchEnrollmentCompletedClassesUseCaseRequest, FetchEnrollmentCompletedClassesUseCaseResponse> { | ||
constructor( | ||
private readonly enrollmentsRepository: EnrollmentsRepository, | ||
private readonly enrollmentCompletedItemsRepository: EnrollmentCompletedItemsRepository | ||
) { } | ||
|
||
async exec({ | ||
enrollmentId | ||
}: FetchEnrollmentCompletedClassesUseCaseRequest): Promise<FetchEnrollmentCompletedClassesUseCaseResponse> { | ||
const enrollment = await this.enrollmentsRepository.findById(enrollmentId) | ||
|
||
if (!enrollment) { | ||
return left(new ResourceNotFoundError()) | ||
} | ||
|
||
const enrollmentCompletedClasses = await this.enrollmentCompletedItemsRepository.findManyCompletedClassesByEnrollmentId( | ||
enrollmentId | ||
) | ||
|
||
return right({ | ||
completedClasses: enrollmentCompletedClasses | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.