-
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, Evaluation): Evaluate class use case
- Loading branch information
1 parent
02961f2
commit d5865a5
Showing
9 changed files
with
418 additions
and
20 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
7 changes: 7 additions & 0 deletions
7
src/domain/course-management/application/repositories/evaluations-repository.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 Evaluation } from '../../enterprise/entities/evaluation' | ||
|
||
export interface EvaluationsRepository { | ||
findById: (id: string) => Promise<Evaluation | null> | ||
findByStudentIdAndClassId: (studentId: string, classId: string) => Promise<Evaluation | null> | ||
create: (evaluation: Evaluation) => Promise<Evaluation> | ||
} |
7 changes: 7 additions & 0 deletions
7
src/domain/course-management/application/use-cases/errors/invalid-evaluation-value-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 InvalidEvaluationValueError extends Error implements UseCaseError { | ||
constructor() { | ||
super('Invalid evaluation value.') | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
...urse-management/application/use-cases/errors/student-already-evaluate-this-class-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 StudentAlreadyEvaluateThisClassError extends Error implements UseCaseError { | ||
constructor(className: string) { | ||
super(`Student already evaluate the class: ${className}.`) | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
...e-management/application/use-cases/errors/student-must-be-registered-to-evaluate-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 StudentMustBeRegisteredToEvaluateError extends Error implements UseCaseError { | ||
constructor(courseName: string) { | ||
super(`Student must be registered in ${courseName} to evaluate.`) | ||
} | ||
} |
254 changes: 254 additions & 0 deletions
254
src/domain/course-management/application/use-cases/evaluate-class.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,254 @@ | ||
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 { 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 { type InMemoryCourseTagsRepository } from '../../../../../test/repositories/in-memory-course-tags-repository' | ||
import { InMemoryCoursesRepository } from '../../../../../test/repositories/in-memory-courses-repository' | ||
import { InMemoryEnrollmentsRepository } from '../../../../../test/repositories/in-memory-enrollments-repository' | ||
import { InMemoryEvaluationsRepository } from '../../../../../test/repositories/in-memory-evaluations-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 { InvalidEvaluationValueError } from './errors/invalid-evaluation-value-error' | ||
import { StudentAlreadyEvaluateThisClassError } from './errors/student-already-evaluate-this-class-error' | ||
import { StudentMustBeRegisteredToEvaluateError } from './errors/student-must-be-registered-to-evaluate-error' | ||
import { EvaluateClassUseCase } from './evaluate-class' | ||
|
||
let inMemoryEnrollmentsRepository: InMemoryEnrollmentsRepository | ||
let inMemoryEvaluationsRepository: InMemoryEvaluationsRepository | ||
let inMemoryCourseTagsRepository: InMemoryCourseTagsRepository | ||
let inMemoryClassesRepository: InMemoryClassesRepository | ||
let inMemoryInstructorsRepository: InMemoryInstructorRepository | ||
let inMemoryStudentsRepository: InMemoryStudentsRepository | ||
let inMemoryModulesRepository: InMemoryModulesRepository | ||
let inMemoryCoursesRepository: InMemoryCoursesRepository | ||
let sut: EvaluateClassUseCase | ||
|
||
describe('Evaluate class use case', () => { | ||
beforeEach(() => { | ||
inMemoryClassesRepository = new InMemoryClassesRepository() | ||
inMemoryEvaluationsRepository = new InMemoryEvaluationsRepository() | ||
inMemoryInstructorsRepository = new InMemoryInstructorRepository() | ||
inMemoryStudentsRepository = new InMemoryStudentsRepository() | ||
|
||
inMemoryModulesRepository = new InMemoryModulesRepository(inMemoryClassesRepository) | ||
|
||
inMemoryEnrollmentsRepository = new InMemoryEnrollmentsRepository( | ||
inMemoryClassesRepository, inMemoryModulesRepository | ||
) | ||
inMemoryCoursesRepository = new InMemoryCoursesRepository(inMemoryModulesRepository, inMemoryInstructorsRepository, inMemoryEnrollmentsRepository, inMemoryStudentsRepository, inMemoryCourseTagsRepository) | ||
|
||
sut = new EvaluateClassUseCase( | ||
inMemoryEvaluationsRepository, | ||
inMemoryStudentsRepository, | ||
inMemoryCoursesRepository, | ||
inMemoryClassesRepository, | ||
inMemoryEnrollmentsRepository | ||
) | ||
}) | ||
|
||
it('should be able to evaluate a class', 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 classToEvaluate = makeClass({ name: 'John Doe Class', moduleId: module.id, classNumber: 1 }) | ||
await inMemoryClassesRepository.create(classToEvaluate) | ||
|
||
const student = makeStudent() | ||
await inMemoryStudentsRepository.create(student) | ||
|
||
const enrollment = makeEnrollment({ courseId: course.id, studentId: student.id }) | ||
await inMemoryEnrollmentsRepository.create(enrollment) | ||
|
||
const result = await sut.exec({ | ||
value: 3, | ||
studentId: student.id.toString(), | ||
courseId: course.id.toString(), | ||
classId: classToEvaluate.id.toString() | ||
}) | ||
|
||
expect(result.isRight()).toBe(true) | ||
expect(result.value).toMatchObject({ | ||
evaluation: expect.objectContaining({ | ||
value: 3, | ||
studentId: student.id, | ||
classId: classToEvaluate.id | ||
}) | ||
}) | ||
}) | ||
|
||
it('should not be able to evaluate a class with an invalid value', 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 classToEvaluate = makeClass({ name: 'John Doe Class', moduleId: module.id, classNumber: 1 }) | ||
await inMemoryClassesRepository.create(classToEvaluate) | ||
|
||
const student = makeStudent() | ||
await inMemoryStudentsRepository.create(student) | ||
|
||
const enrollment = makeEnrollment({ courseId: course.id, studentId: student.id }) | ||
await inMemoryEnrollmentsRepository.create(enrollment) | ||
|
||
const result = await sut.exec({ | ||
value: 7, // The rating must be from 1 to 5 | ||
studentId: student.id.toString(), | ||
courseId: course.id.toString(), | ||
classId: classToEvaluate.id.toString() | ||
}) | ||
|
||
expect(result.isLeft()).toBe(true) | ||
expect(result.value).toBeInstanceOf(InvalidEvaluationValueError) | ||
}) | ||
|
||
it('should not be able to evaluate a inexistent class', 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 student = makeStudent() | ||
await inMemoryStudentsRepository.create(student) | ||
|
||
const enrollment = makeEnrollment({ courseId: course.id, studentId: student.id }) | ||
await inMemoryEnrollmentsRepository.create(enrollment) | ||
|
||
const result = await sut.exec({ | ||
value: 3, | ||
studentId: student.id.toString(), | ||
courseId: course.id.toString(), | ||
classId: 'inexistentClassId' | ||
}) | ||
|
||
expect(result.isLeft()).toBe(true) | ||
expect(result.value).toBeInstanceOf(ResourceNotFoundError) | ||
}) | ||
|
||
it('an inexistent student should not be able to evaluate a class', 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 classToEvaluate = makeClass({ name: 'John Doe Class', moduleId: module.id, classNumber: 1 }) | ||
await inMemoryClassesRepository.create(classToEvaluate) | ||
|
||
const result = await sut.exec({ | ||
value: 3, | ||
studentId: 'inexistentStudentId', | ||
courseId: course.id.toString(), | ||
classId: classToEvaluate.id.toString() | ||
}) | ||
|
||
expect(result.isLeft()).toBe(true) | ||
expect(result.value).toBeInstanceOf(ResourceNotFoundError) | ||
}) | ||
|
||
it('an student should not be able to evaluate a same class twice', 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 classToEvaluate = makeClass({ name: 'John Doe Class', moduleId: module.id, classNumber: 1 }) | ||
await inMemoryClassesRepository.create(classToEvaluate) | ||
|
||
const student = makeStudent() | ||
await inMemoryStudentsRepository.create(student) | ||
|
||
const enrollment = makeEnrollment({ courseId: course.id, studentId: student.id }) | ||
await inMemoryEnrollmentsRepository.create(enrollment) | ||
|
||
await sut.exec({ | ||
value: 3, | ||
studentId: student.id.toString(), | ||
courseId: course.id.toString(), | ||
classId: classToEvaluate.id.toString() | ||
}) | ||
|
||
const result = await sut.exec({ | ||
value: 3, | ||
studentId: student.id.toString(), | ||
courseId: course.id.toString(), | ||
classId: classToEvaluate.id.toString() | ||
}) | ||
|
||
expect(result.isLeft()).toBe(true) | ||
expect(result.value).toBeInstanceOf(StudentAlreadyEvaluateThisClassError) | ||
}) | ||
|
||
it('should not be able to evaluate a class if the student is not enrolled in the respective course', 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 classToEvaluate = makeClass({ name: 'John Doe Class', moduleId: module.id, classNumber: 1 }) | ||
await inMemoryClassesRepository.create(classToEvaluate) | ||
|
||
const student = makeStudent() | ||
await inMemoryStudentsRepository.create(student) | ||
|
||
// Not enrolled in the course | ||
|
||
const result = await sut.exec({ | ||
value: 3, | ||
studentId: student.id.toString(), | ||
courseId: course.id.toString(), | ||
classId: classToEvaluate.id.toString() | ||
}) | ||
|
||
expect(result.isLeft()).toBe(true) | ||
expect(result.value).toBeInstanceOf(StudentMustBeRegisteredToEvaluateError) | ||
}) | ||
}) |
Oops, something went wrong.