diff --git a/pom.xml b/pom.xml
index 7e35f61..dee52ab 100644
--- a/pom.xml
+++ b/pom.xml
@@ -21,7 +21,6 @@
org.springframework.boot
spring-boot-starter-web
-
org.springframework.boot
spring-boot-devtools
@@ -47,6 +46,18 @@
spring-security-crypto
3.1.0.RELEASE
+
+
+ org.seleniumhq.selenium
+ selenium-java
+
+
+ org.seleniumhq.selenium
+ selenium-api
+ test
+
+
+
diff --git a/src/main/java/com/cst438/Cst438Assignment2Main.java b/src/main/java/com/cst438/Cst438Assignment2Main.java
index a0bcaf6..e811fbd 100644
--- a/src/main/java/com/cst438/Cst438Assignment2Main.java
+++ b/src/main/java/com/cst438/Cst438Assignment2Main.java
@@ -10,4 +10,6 @@ public static void main(String[] args) {
SpringApplication.run(Cst438Assignment2Main.class, args);
}
+
+
}
diff --git a/src/main/java/com/cst438/controller/AssignmentController.java b/src/main/java/com/cst438/controller/AssignmentController.java
index 4d0ad35..d437289 100644
--- a/src/main/java/com/cst438/controller/AssignmentController.java
+++ b/src/main/java/com/cst438/controller/AssignmentController.java
@@ -16,11 +16,22 @@
import java.util.ArrayList;
import java.util.List;
+import java.sql.Date;
@RestController
@CrossOrigin(origins = "http://localhost:3000")
public class AssignmentController {
+ @Autowired
+ AssignmentRepository assignmentRepository;
+ @Autowired
+ CourseRepository courseRepository;
+ @Autowired
+ SectionRepository sectionRepository;
+ @Autowired
+ EnrollmentRepository enrollmentRepository;
+ @Autowired
+ GradeRepository gradeRepository;
// instructor lists assignments for a section. Assignments ordered by due date.
// logged in user must be the instructor for the section
@@ -28,25 +39,70 @@ public class AssignmentController {
public List getAssignments(
@PathVariable("secNo") int secNo) {
- // TODO remove the following line when done
-
- // hint: use the assignment repository method
- // findBySectionNoOrderByDueDate to return
- // a list of assignments
-
- return null;
+ List assignments = assignmentRepository.findBySectionNoOrderByDueDate(secNo);
+ if (assignments.isEmpty()) {
+ throw new ResponseStatusException( HttpStatus.NOT_FOUND, "section not found " + secNo);
+ }
+ List dto_list = new ArrayList<>();
+ for(Assignment a:assignments){
+ dto_list.add(new AssignmentDTO(
+ a.getAssignmentId(),
+ a.getTitle(),
+ a.getDueDate().toString(),
+ a.getSection().getCourse().getCourseId(),
+ a.getSection().getSecId(),
+ a.getSection().getSectionNo()
+ ));
+ }
+
+ // hint: use the assignment repository method
+ // findBySectionNoOrderByDueDate to return
+ // a list of assignments
+
+ return dto_list;
}
// add assignment
// user must be instructor of the section
// return AssignmentDTO with assignmentID generated by database
@PostMapping("/assignments")
- public AssignmentDTO createAssignment(
- @RequestBody AssignmentDTO dto) {
+ public AssignmentDTO createAssignment(@RequestBody AssignmentDTO dto) {
- // TODO remove the following line when done
+ Section s = sectionRepository.findSectionBySectionNo(dto.secNo());
+ if (s==null) {
+ throw new ResponseStatusException(HttpStatus.NOT_FOUND, "section not found " + dto.secNo());
+ }
+ if(s.getSectionNo()!=dto.secNo()){
+ throw new ResponseStatusException(HttpStatus.NOT_FOUND, "sectionNo not matched " + dto.secNo());
+ }
- return null;
+ // TODO remove the following line when done
+ Assignment a = new Assignment();
+ a.setAssignmentId(dto.id());
+ a.setTitle(dto.title());
+ //convert string -> date
+ Date date = Date.valueOf(dto.dueDate());
+
+ Date startDate = s.getTerm().getStartDate();
+ Date dropDate = s.getTerm().getEndDate();
+ if(date.before(startDate)){
+ throw new ResponseStatusException(HttpStatus.NOT_FOUND, "DueDate is before course StartDate ");
+ }if(date.after(dropDate)){
+ throw new ResponseStatusException(HttpStatus.NOT_FOUND, "DueDate is after course EndDate ");
+ }
+
+ a.setDueDate(date);
+ a.setSection(s);
+ assignmentRepository.save(a);
+
+ return new AssignmentDTO(
+ a.getAssignmentId(),
+ a.getTitle(),
+ a.getDueDate().toString(),
+ a.getSection().getCourse().getCourseId(),
+ a.getSection().getSecId(),
+ a.getSection().getSectionNo()
+ );
}
// update assignment for a section. Only title and dueDate may be changed.
@@ -55,9 +111,33 @@ public AssignmentDTO createAssignment(
@PutMapping("/assignments")
public AssignmentDTO updateAssignment(@RequestBody AssignmentDTO dto) {
- // TODO remove the following line when done
-
- return null;
+ Assignment a = assignmentRepository.findById(dto.id()).orElse(null);
+ if(a==null){
+ throw new ResponseStatusException( HttpStatus.NOT_FOUND, "Assignment not found "+dto.id());
+ }
+
+ a.setTitle(dto.title());
+ //convert string -> date
+ Date date = Date.valueOf(dto.dueDate());
+
+ Date startDate = a.getSection().getTerm().getStartDate();
+ Date dropDate = a.getSection().getTerm().getEndDate();
+ if(date.before(startDate)){
+ throw new ResponseStatusException(HttpStatus.NOT_FOUND, "DueDate is before course StartDate ");
+ }if(date.after(dropDate)){
+ throw new ResponseStatusException(HttpStatus.NOT_FOUND, "DueDate is after course EndDate ");
+ }
+
+ a.setDueDate(date);
+ assignmentRepository.save(a);
+ return new AssignmentDTO(
+ a.getAssignmentId(),
+ a.getTitle(),
+ a.getDueDate().toString(),
+ a.getSection().getCourse().getCourseId(),
+ a.getSection().getSecId(),
+ a.getSection().getSectionNo()
+ );
}
// delete assignment for a section
@@ -65,7 +145,11 @@ public AssignmentDTO updateAssignment(@RequestBody AssignmentDTO dto) {
@DeleteMapping("/assignments/{assignmentId}")
public void deleteAssignment(@PathVariable("assignmentId") int assignmentId) {
- // TODO
+ Assignment a = assignmentRepository.findById(assignmentId).orElse(null);
+ //if assignment doesn't exist, do nothing
+ if(a!=null){
+ assignmentRepository.delete(a);
+ }
}
// instructor gets grades for assignment ordered by student name
@@ -74,15 +158,46 @@ public void deleteAssignment(@PathVariable("assignmentId") int assignmentId) {
public List getAssignmentGrades(@PathVariable("assignmentId") int assignmentId) {
// TODO remove the following line when done
+ Assignment a = assignmentRepository.findById(assignmentId).orElse(null);
+ if (a==null) {
+ throw new ResponseStatusException( HttpStatus.NOT_FOUND, "assignment not found "+assignmentId);
+ }
// get the list of enrollments for the section related to this assignment.
- // hint: use te enrollment repository method findEnrollmentsBySectionOrderByStudentName.
- // for each enrollment, get the grade related to the assignment and enrollment
- // hint: use the gradeRepository findByEnrollmentIdAndAssignmentId method.
- // if the grade does not exist, create a grade entity and set the score to NULL
- // and then save the new entity
+ // hint: use the enrollment repository method findEnrollmentsBySectionOrderByStudentName.
+ List enrollments = enrollmentRepository.findEnrollmentsBySectionNoOrderByStudentName(a.getSection().getSectionNo());
+ if (enrollments.isEmpty()) {
+ throw new ResponseStatusException( HttpStatus.NOT_FOUND, "Enrollment not found");
+ }
- return null;
+ // for each enrollment, get the grade related to the assignment and enrollment
+ // hint: use the gradeRepository findByEnrollmentIdAndAssignmentId method.
+ List gradeDTOList = new ArrayList<>();
+ if(enrollments.isEmpty()){
+ throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Enrollment not found");
+ }
+ for(Enrollment e:enrollments){
+ // if the grade does not exist, create a grade entity and set the score to NULL
+ Grade g = gradeRepository.findByEnrollmentIdAndAssignmentId(e.getEnrollmentId(), assignmentId);
+ if(g==null){
+ g = new Grade();
+ g.setAssignment(a);
+ g.setEnrollment(e);
+ g.setScore(null);
+ // and then save the new entity
+ gradeRepository.save(g);
+ }
+ gradeDTOList.add(new GradeDTO(
+ g.getGradeId(),
+ e.getStudent().getName(),
+ e.getStudent().getEmail(),
+ a.getTitle(),
+ e.getSection().getCourse().getCourseId(),
+ e.getSection().getSecId(),
+ g.getScore()
+ ));
+ }
+ return gradeDTOList;
}
// instructor uploads grades for assignment
@@ -90,15 +205,18 @@ public List getAssignmentGrades(@PathVariable("assignmentId") int assi
@PutMapping("/grades")
public void updateGrades(@RequestBody List dlist) {
- // TODO
-
// for each grade in the GradeDTO list, retrieve the grade entity
- // update the score and save the entity
-
+ for(GradeDTO dto:dlist){
+ Grade g = gradeRepository.findById(dto.gradeId()).orElse(null);
+ if(g==null){
+ throw new ResponseStatusException( HttpStatus.NOT_FOUND, "Grade not found "+dto.gradeId());
+ }
+ // update the score and save the entity
+ g.setScore(dto.score());
+ gradeRepository.save(g);
+ }
}
-
-
// student lists their assignments/grades for an enrollment ordered by due date
// student must be enrolled in the section
@GetMapping("/assignments")
@@ -108,11 +226,29 @@ public List getStudentAssignments(
@RequestParam("semester") String semester) {
// TODO remove the following line when done
+ List returnDtos = new ArrayList<>();
+ List enrollments = enrollmentRepository.findByYearAndSemesterOrderByCourseId(year, semester, studentId);
+ List assignments = new ArrayList<>();
+ for (Enrollment e:enrollments){
+ assignments = assignmentRepository.findBySectionNoOrderByDueDate(e.getSection().getSectionNo());
+ for(Assignment a:assignments){
+ Grade grade = gradeRepository.findByEnrollmentIdAndAssignmentId(e.getEnrollmentId(), a.getAssignmentId());
+ returnDtos.add(new AssignmentStudentDTO(
+ a.getAssignmentId(),
+ a.getTitle(),
+ a.getDueDate(),
+ e.getSection().getCourse().getCourseId(),
+ e.getSection().getSecId(),
+ (grade!=null) ? grade.getScore() : null
+ ));
+ }
+ }
+
// return a list of assignments and (if they exist) the assignment grade
// for all sections that the student is enrolled for the given year and semester
- // hint: use the assignment repository method findByStudentIdAndYearAndSemesterOrderByDueDate
+ // hint: use the assignment repository method findByStudentIdAndYearAndSemesterOrderByDueDate
- return null;
+ return returnDtos;
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/com/cst438/controller/EnrollmentController.java b/src/main/java/com/cst438/controller/EnrollmentController.java
index bcccc61..c88efd8 100644
--- a/src/main/java/com/cst438/controller/EnrollmentController.java
+++ b/src/main/java/com/cst438/controller/EnrollmentController.java
@@ -1,42 +1,62 @@
package com.cst438.controller;
-
+import com.cst438.domain.Enrollment;
+import com.cst438.domain.EnrollmentRepository;
import com.cst438.dto.EnrollmentDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;
-import java.util.ArrayList;
import java.util.List;
+import java.util.stream.Collectors;
@RestController
@CrossOrigin(origins = "http://localhost:3000")
public class EnrollmentController {
+ @Autowired
+ private EnrollmentRepository enrollmentRepository;
+
// instructor downloads student enrollments for a section, ordered by student name
// user must be instructor for the section
@GetMapping("/sections/{sectionNo}/enrollments")
- public List getEnrollments(
- @PathVariable("sectionNo") int sectionNo ) {
-
- // TODO
- // hint: use enrollment repository findEnrollmentsBySectionNoOrderByStudentName method
- // remove the following line when done
- return null;
+ public List getEnrollments(@PathVariable("sectionNo") int sectionNo) {
+ List enrollments = enrollmentRepository.findEnrollmentsBySectionNoOrderByStudentName(sectionNo);
+ if(enrollments == null) {
+ throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Section number is invalid");
+ }
+
+ return enrollments.stream()
+ .map(enrollment -> new EnrollmentDTO(
+ enrollment.getEnrollmentId(),
+ enrollment.getGrade(),
+ enrollment.getStudent().getId(),
+ enrollment.getStudent().getName(),
+ enrollment.getStudent().getEmail(),
+ enrollment.getSection().getCourse().getCourseId(),
+ enrollment.getSection().getSecId(),
+ enrollment.getSection().getSectionNo(),
+ enrollment.getSection().getBuilding(),
+ enrollment.getSection().getRoom(),
+ enrollment.getSection().getTimes(),
+ enrollment.getSection().getCourse().getCredits(),
+ enrollment.getSection().getTerm().getYear(),
+ enrollment.getSection().getTerm().getSemester()))
+ .collect(Collectors.toList());
}
// instructor uploads enrollments with the final grades for the section
// user must be instructor for the section
@PutMapping("/enrollments")
- public void updateEnrollmentGrade(@RequestBody List dlist) {
-
- // TODO
-
- // For each EnrollmentDTO in the list
- // find the Enrollment entity using enrollmentId
- // update the grade and save back to database
-
+ public void updateEnrollmentGrade(@RequestBody List dtoList) {
+ for (EnrollmentDTO dto : dtoList) {
+ Enrollment enrollment = enrollmentRepository.findById(dto.enrollmentId())
+ .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Enrollment not found"));
+
+ // Update the grade and save back to the database
+ enrollment.setGrade(dto.grade());
+ enrollmentRepository.save(enrollment);
+ }
}
-
-}
+}
\ No newline at end of file
diff --git a/src/main/java/com/cst438/controller/SectionController.java b/src/main/java/com/cst438/controller/SectionController.java
index 746c624..2a0540c 100644
--- a/src/main/java/com/cst438/controller/SectionController.java
+++ b/src/main/java/com/cst438/controller/SectionController.java
@@ -6,6 +6,8 @@
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
@@ -14,6 +16,7 @@
@CrossOrigin(origins = "http://localhost:3000")
public class SectionController {
+ private static final Logger logger = LoggerFactory.getLogger(SectionController.class.getName());
@Autowired
CourseRepository courseRepository;
@@ -152,12 +155,15 @@ public List getSections(
@GetMapping("/sections")
public List getSectionsForInstructor(
@RequestParam("email") String instructorEmail,
- @RequestParam("year") int year ,
- @RequestParam("semester") String semester ) {
+ @RequestParam("year") int year,
+ @RequestParam("semester") String semester) {
+ logger.info("Fetching sections for instructor: {}, year: {}, semester: {}", instructorEmail, year, semester);
List sections = sectionRepository.findByInstructorEmailAndYearAndSemester(instructorEmail, year, semester);
+ logger.info("Found {} sections for instructor: {}, year: {}, semester: {}", sections.size(), instructorEmail, year, semester);
+
List dto_list = new ArrayList<>();
for (Section s : sections) {
User instructor = null;
@@ -179,7 +185,7 @@ public List getSectionsForInstructor(
}
return dto_list;
}
-
+
@GetMapping("/sections/open")
public List getOpenSectionsForEnrollment() {
@@ -203,4 +209,4 @@ public List getOpenSectionsForEnrollment() {
}
return dlist;
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/com/cst438/controller/StudentController.java b/src/main/java/com/cst438/controller/StudentController.java
index e34f59f..46c1942 100644
--- a/src/main/java/com/cst438/controller/StudentController.java
+++ b/src/main/java/com/cst438/controller/StudentController.java
@@ -1,7 +1,9 @@
package com.cst438.controller;
import com.cst438.domain.*;
+import com.cst438.dto.CourseDTO;
import com.cst438.dto.EnrollmentDTO;
+import com.sun.tools.jconsole.JConsoleContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
@@ -9,6 +11,7 @@
import java.util.ArrayList;
import java.util.Date;
+import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Optional;
@@ -16,6 +19,21 @@
@CrossOrigin(origins = "http://localhost:3000")
public class StudentController {
+ @Autowired
+ CourseRepository courseRepository;
+
+ @Autowired
+ SectionRepository sectionRepository;
+
+ @Autowired
+ TermRepository termRepository;
+
+ @Autowired
+ UserRepository userRepository;
+
+ @Autowired
+ EnrollmentRepository enrollmentRepository;
+
// student gets transcript showing list of all enrollments
// studentId will be temporary until Login security is implemented
@@ -23,13 +41,43 @@ public class StudentController {
@GetMapping("/transcripts")
public List getTranscript(@RequestParam("studentId") int studentId) {
- // TODO
-
// list course_id, sec_id, title, credit, grade in chronological order
// user must be a student
// hint: use enrollment repository method findEnrollmentByStudentIdOrderByTermId
- // remove the following line when done
- return null;
+
+ List enrollments = enrollmentRepository.findEnrollmentsByStudentIdOrderByTermId(studentId);
+ List dto_list = new ArrayList<>();
+ boolean studentFound = false;
+ for (Enrollment e : enrollments) {
+ if (e.getStudent().getId() == studentId) {
+ studentFound = true;
+ break;
+ }
+ }
+ if (!studentFound) {
+ throw new ResponseStatusException( HttpStatus.NOT_FOUND, "Student not found "+ studentId);
+ } else {
+ for (Enrollment e : enrollments) {
+ dto_list.add(new EnrollmentDTO(
+ e.getEnrollmentId(),
+ e.getGrade(),
+ studentId,
+ e.getStudent().getName(),
+ e.getStudent().getEmail(),
+ e.getSection().getCourse().getCourseId(),
+ e.getSection().getSecId(),
+ e.getSection().getSectionNo(),
+ e.getSection().getBuilding(),
+ e.getSection().getRoom(),
+ e.getSection().getTimes(),
+ e.getSection().getCourse().getCredits(),
+ e.getSection().getTerm().getYear(),
+ e.getSection().getTerm().getSemester()));
+ }
+
+ return dto_list;
+
+ }
}
// student gets a list of their enrollments for the given year, semester
@@ -41,14 +89,36 @@ public List getSchedule(
@RequestParam("semester") String semester,
@RequestParam("studentId") int studentId) {
-
// TODO
// hint: use enrollment repository method findByYearAndSemesterOrderByCourseId
- // remove the following line when done
- return null;
+ List enrollments = enrollmentRepository.findByYearAndSemesterOrderByCourseId(year, semester, studentId);
+ if (enrollments.isEmpty()) {
+ throw new ResponseStatusException( HttpStatus.NOT_FOUND, "Enrollment not found");
+ }
+ List dto_list = new ArrayList<>();
+ for (Enrollment e : enrollments) {
+ dto_list.add(new EnrollmentDTO(
+ e.getEnrollmentId(),
+ e.getGrade(),
+ studentId,
+ e.getStudent().getName(),
+ e.getStudent().getEmail(),
+ e.getSection().getCourse().getCourseId(),
+ e.getSection().getSecId(),
+ e.getSection().getSectionNo(),
+ e.getSection().getBuilding(),
+ e.getSection().getRoom(),
+ e.getSection().getTimes(),
+ e.getSection().getCourse().getCredits(),
+ e.getSection().getTerm().getYear(),
+ e.getSection().getTerm().getSemester()));
+ }
+
+ return dto_list;
+
+ // return null;
}
-
// student adds enrollment into a section
// user must be student
// return EnrollmentDTO with enrollmentId generated by database
@@ -58,24 +128,87 @@ public EnrollmentDTO addCourse(
@RequestParam("studentId") int studentId ) {
// TODO
-
// check that the Section entity with primary key sectionNo exists
+ Section s = sectionRepository.findById(sectionNo).orElse(null);
+ if (s==null){
+ throw new ResponseStatusException( HttpStatus.NOT_FOUND, "section not found " + sectionNo);
+ }
+
// check that today is between addDate and addDeadline for the section
+ long millis = System.currentTimeMillis();
+ java.sql.Date today = new java.sql.Date(millis);
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-mm-dd");
+ Date addDate = s.getTerm().getAddDate();
+ Date addDeadline = s.getTerm().getAddDeadline();
+ if (today.before(addDate) || today.after(addDeadline)) {
+ throw new ResponseStatusException( HttpStatus.BAD_REQUEST, "Invalid date");
+ }
+
// check that student is not already enrolled into this section
+ Enrollment e = enrollmentRepository.findEnrollmentBySectionNoAndStudentId(sectionNo, studentId);
+ Section section = sectionRepository.findSectionBySectionNo(sectionNo);
+ List users = userRepository.findAllByOrderByIdAsc();
+ User student = new User();
+ for (User u : users) {
+ if (u.getId() == studentId) {
+ student = u;
+ break;
+ }
+ }
+
// create a new enrollment entity and save. The enrollment grade will
// be NULL until instructor enters final grades for the course.
-
- // remove the following line when done.
- return null;
+ if (e != null) {
+ throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "already enrolled in this section");
+ } else {
+ e = new Enrollment();
+ e.setSection(section);
+ e.setUser(student);
+ enrollmentRepository.save(e);
+ return new EnrollmentDTO(
+ e.getEnrollmentId(),
+ "",
+ studentId,
+ e.getStudent().getName(),
+ e.getStudent().getEmail(),
+ e.getSection().getCourse().getCourseId(),
+ e.getSection().getSecId(),
+ e.getSection().getSectionNo(),
+ e.getSection().getBuilding(),
+ e.getSection().getRoom(),
+ e.getSection().getTimes(),
+ e.getSection().getCourse().getCredits(),
+ e.getSection().getTerm().getYear(),
+ e.getSection().getTerm().getSemester()
+ );
+ }
}
// student drops a course
- // user must be student
@DeleteMapping("/enrollments/{enrollmentId}")
public void dropCourse(@PathVariable("enrollmentId") int enrollmentId) {
- // TODO
+ Enrollment e = enrollmentRepository.findEnrollmentByEnrollmentId(enrollmentId);
+ if (e == null) {
+ throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Enrollment does not exist");
+ }
+
+ // user must be student
+ if (!e.getStudent().getType().equals("STUDENT")) {
+ throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "User must be student");
+ }
+
// check that today is not after the dropDeadline for section
+ long millis = System.currentTimeMillis();
+ java.sql.Date today = new java.sql.Date(millis);
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-mm-dd");
+ Date dropDate = e.getSection().getTerm().getDropDeadline();
+ if (today.after(dropDate)) {
+ throw new ResponseStatusException( HttpStatus.BAD_REQUEST, "Too late to drop. Sorry, the money is ours");
+ } else {
+ enrollmentRepository.delete(e);
+ }
+
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/cst438/domain/Assignment.java b/src/main/java/com/cst438/domain/Assignment.java
index c669834..d4a4372 100644
--- a/src/main/java/com/cst438/domain/Assignment.java
+++ b/src/main/java/com/cst438/domain/Assignment.java
@@ -4,16 +4,56 @@
import java.sql.Date;
import java.text.SimpleDateFormat;
-
+//Change!
@Entity
public class Assignment {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="assignment_id")
private int assignmentId;
-
- // TODO complete this class
+
// add additional attributes for title, dueDate
+ private String title;
+
+ @Column(name = "due_date")
+ private Date dueDate;
// add relationship between assignment and section entities
+ @ManyToOne
+ @JoinColumn(name = "section_no", nullable = false)
+ private Section section;
// add getter and setter methods
+
+ public int getAssignmentId() {
+ return assignmentId;
+ }
+
+ public void setAssignmentId(int assignmentId) {
+ this.assignmentId = assignmentId;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public Date getDueDate() {
+ return dueDate;
+ }
+
+ public void setDueDate(Date dueDate) {
+ this.dueDate = dueDate;
+ }
+
+ public Section getSection() {
+ return section;
+ }
+
+ public void setSection(Section section) {
+ this.section = section;
+ }
+
+
}
diff --git a/src/main/java/com/cst438/domain/AssignmentRepository.java b/src/main/java/com/cst438/domain/AssignmentRepository.java
index 2f04eaa..4d533a7 100644
--- a/src/main/java/com/cst438/domain/AssignmentRepository.java
+++ b/src/main/java/com/cst438/domain/AssignmentRepository.java
@@ -8,13 +8,14 @@
public interface AssignmentRepository extends CrudRepository {
// TODO uncomment the following lines as needed
+ // This is my comment
-// @Query("select a from Assignment a where a.section.sectionNo=:sectionNo order by a.dueDate")
-// List findBySectionNoOrderByDueDate(int sectionNo);
-//
-// @Query("select a from Assignment a join a.section.enrollments e " +
-// "where a.section.term.year=:year and a.section.term.semester=:semester and" +
-// " e.student.id=:studentId order by a.dueDate")
-// List findByStudentIdAndYearAndSemesterOrderByDueDate(int studentId, int year, String semester);
+ @Query("select a from Assignment a where a.section.sectionNo=:sectionNo order by a.dueDate")
+ List findBySectionNoOrderByDueDate(int sectionNo);
+
+ @Query("select a from Assignment a join a.section.enrollments e " +
+ "where a.section.term.year=:year and a.section.term.semester=:semester and" +
+ " e.student.id=:studentId order by a.dueDate")
+ List findByStudentIdAndYearAndSemesterOrderByDueDate(int studentId, int year, String semester);
}
diff --git a/src/main/java/com/cst438/domain/CourseRepository.java b/src/main/java/com/cst438/domain/CourseRepository.java
index 3cc6216..328c742 100644
--- a/src/main/java/com/cst438/domain/CourseRepository.java
+++ b/src/main/java/com/cst438/domain/CourseRepository.java
@@ -4,6 +4,6 @@
import java.util.List;
public interface CourseRepository extends CrudRepository {
-
+
List findAllByOrderByCourseIdAsc();
-}
+}
\ No newline at end of file
diff --git a/src/main/java/com/cst438/domain/Enrollment.java b/src/main/java/com/cst438/domain/Enrollment.java
index a7f27c7..37c9ed9 100644
--- a/src/main/java/com/cst438/domain/Enrollment.java
+++ b/src/main/java/com/cst438/domain/Enrollment.java
@@ -11,7 +11,45 @@ public class Enrollment {
// TODO complete this class
// add additional attribute for grade
+ private String grade;
+
// create relationship between enrollment and user entities
+ @ManyToOne
+ @JoinColumn(name = "user_id",nullable = false)
+ private User student;
+
// create relationship between enrollment and section entities
+ @ManyToOne
+ @JoinColumn(name = "section_no", nullable = false)
+ private Section section;
+
// add getter/setter methods
+
+ public int getEnrollmentId(){
+ return enrollmentId;
+ }
+ public void setEnrollmentId(int enrollmentId){
+ this.enrollmentId = enrollmentId;
+ }
+
+ public String getGrade(){
+ return grade;
+ }
+ public void setGrade(String grade){
+ this.grade = grade;
+ }
+
+ public User getStudent(){
+ return student;
+ }
+ public void setUser(User student){
+ this.student = student;
+ }
+
+ public Section getSection(){
+ return section;
+ }
+ public void setSection(Section section){
+ this.section = section;
+ }
}
diff --git a/src/main/java/com/cst438/domain/EnrollmentRepository.java b/src/main/java/com/cst438/domain/EnrollmentRepository.java
index 4ac3267..d68c11d 100644
--- a/src/main/java/com/cst438/domain/EnrollmentRepository.java
+++ b/src/main/java/com/cst438/domain/EnrollmentRepository.java
@@ -9,15 +9,19 @@ public interface EnrollmentRepository extends CrudRepository findEnrollmentsBySectionNoOrderByStudentName(int sectionNo);
-//
-// @Query("select e from Enrollment e where e.student.id=:studentId order by e.section.term.termId")
-// List findEnrollmentsByStudentIdOrderByTermId(int studentId);
-//
-// @Query("select e from Enrollment e where e.section.term.year=:year and e.section.term.semester=:semester and e.student.id=:studentId order by e.section.course.courseId")
-// List findByYearAndSemesterOrderByCourseId(int year, String semester, int studentId);
-//
-// @Query("select e from Enrollment e where e.section.sectionNo=:sectionNo and e.student.id=:studentId")
-// Enrollment findEnrollmentBySectionNoAndStudentId(int sectionNo, int studentId);
+
+ @Query("select e from Enrollment e where e.section.sectionNo=:sectionNo order by e.student.name")
+ List findEnrollmentsBySectionNoOrderByStudentName(int sectionNo);
+
+ @Query("select e from Enrollment e where e.student.id=:studentId order by e.section.term.termId")
+ List findEnrollmentsByStudentIdOrderByTermId(int studentId);
+
+ @Query("select e from Enrollment e where e.section.term.year=:year and e.section.term.semester=:semester and e.student.id=:studentId order by e.section.course.courseId")
+ List findByYearAndSemesterOrderByCourseId(int year, String semester, int studentId);
+
+ @Query("select e from Enrollment e where e.section.sectionNo=:sectionNo and e.student.id=:studentId")
+ Enrollment findEnrollmentBySectionNoAndStudentId(int sectionNo, int studentId);
+
+ @Query("select e from Enrollment e where e.enrollmentId=:enrollmentId")
+ Enrollment findEnrollmentByEnrollmentId(int enrollmentId);
}
diff --git a/src/main/java/com/cst438/domain/Grade.java b/src/main/java/com/cst438/domain/Grade.java
index c5d6514..b7db4dd 100644
--- a/src/main/java/com/cst438/domain/Grade.java
+++ b/src/main/java/com/cst438/domain/Grade.java
@@ -8,10 +8,29 @@ public class Grade {
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="grade_id")
private int gradeId;
-
+
// TODO complete this class
- // add additional attribute for score
+
// add relationship between grade and assignment entities
+ @ManyToOne
+ @JoinColumn(name="assignment_id")
+ private Assignment assignment;
// add relationship between grade and enrollment entities
+ @ManyToOne
+ @JoinColumn(name="enrollment_id")
+ private Enrollment enrollment;
+ // add additional attribute for score
+ @Column(name="score")
+ private Integer score;
+
// add getter/setter methods
-}
+ public int getGradeId() {return gradeId; }
+ public void setGradeId(int gradeId) {this.gradeId = gradeId; }
+ public Integer getScore() {return score; }
+ public void setScore (Integer score) {this.score = score; }
+ public Assignment getAssignment() {return assignment; }
+ public void setAssignment(Assignment assignment) {this.assignment = assignment; }
+ public Enrollment getEnrollment() {return enrollment; }
+ public void setEnrollment(Enrollment enrollment) {this.enrollment = enrollment; }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/cst438/domain/GradeRepository.java b/src/main/java/com/cst438/domain/GradeRepository.java
index ddb6155..78028c1 100644
--- a/src/main/java/com/cst438/domain/GradeRepository.java
+++ b/src/main/java/com/cst438/domain/GradeRepository.java
@@ -7,6 +7,8 @@ public interface GradeRepository extends CrudRepository {
// TODO uncomment the following lines as needed
-// @Query("select g from Grade g where g.assignment.assignmentId=:assignmentId and g.enrollment.enrollmentId=:enrollmentId")
-// Grade findByEnrollmentIdAndAssignmentId(int enrollmentId, int assignmentId);
+ @Query("select g from Grade g where g.assignment.assignmentId=:assignmentId and g.enrollment.enrollmentId=:enrollmentId")
+ Grade findByEnrollmentIdAndAssignmentId(int enrollmentId, int assignmentId);
+
+
}
diff --git a/src/main/java/com/cst438/domain/Section.java b/src/main/java/com/cst438/domain/Section.java
index 0fe2417..8003345 100644
--- a/src/main/java/com/cst438/domain/Section.java
+++ b/src/main/java/com/cst438/domain/Section.java
@@ -29,11 +29,11 @@ public class Section {
// TODO uncomment the following lines
-// @OneToMany(mappedBy="section")
-// List enrollments;
+ @OneToMany(mappedBy="section")
+ List enrollments;
-// @OneToMany(mappedBy="section")
-// List assignments;
+ @OneToMany(mappedBy="section")
+ List assignments;
public int getSectionNo() {
return sectionNo;
diff --git a/src/main/java/com/cst438/domain/SectionRepository.java b/src/main/java/com/cst438/domain/SectionRepository.java
index 6e46cc0..a1b0400 100644
--- a/src/main/java/com/cst438/domain/SectionRepository.java
+++ b/src/main/java/com/cst438/domain/SectionRepository.java
@@ -18,4 +18,7 @@ public interface SectionRepository extends CrudRepository {
@Query("select s from Section s where current_date between s.term.addDate and s.term.addDeadline " +
" order by s.course.courseId, s.secId")
List findByOpenOrderByCourseIdSectionId();
+
+ @Query("select s from Section s where s.sectionNo=:sectionNo")
+ Section findSectionBySectionNo(int sectionNo);
}
diff --git a/src/test/java/com/cst438/controller/AssignmentControllerSystemTest.java b/src/test/java/com/cst438/controller/AssignmentControllerSystemTest.java
new file mode 100644
index 0000000..42594c7
--- /dev/null
+++ b/src/test/java/com/cst438/controller/AssignmentControllerSystemTest.java
@@ -0,0 +1,162 @@
+package com.cst438.controller;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.openqa.selenium.*;
+import org.openqa.selenium.chrome.ChromeDriver;
+import org.openqa.selenium.chrome.ChromeOptions;
+import org.openqa.selenium.interactions.Actions;
+import org.openqa.selenium.support.ui.ExpectedConditions;
+import org.openqa.selenium.support.ui.WebDriverWait;
+
+import java.time.Duration;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+
+public class AssignmentControllerSystemTest {
+
+ //Path to selenium driver
+ public static final String CHROME_DRIVER_FILE_LOCATION =
+ "/Users/kyleabsten/Library/Mobile Documents/com~apple~CloudDocs/CSUMB/CST438_SoftwareEngineering/downloads/chromedriver-mac-arm64/chromedriver";
+
+ //Url of react/nodejs server
+ public static final String reactURL = "http://localhost:3000";
+
+ //Sleep variable = 1 second
+ public static final int SLEEP_DURATION = 1000;
+
+
+ WebDriver driver;
+
+ @BeforeEach
+ public void setUpDriver() throws Exception {
+ //Set properties required by Chrome driver
+ System.setProperty(
+ "webdriver.chrome.driver", CHROME_DRIVER_FILE_LOCATION);
+ ChromeOptions ops = new ChromeOptions();
+ ops.addArguments("--remote-allow-origins=*");
+ ops.addArguments("--no-sandbox");
+
+ //Start driver
+ driver = new ChromeDriver(ops);
+
+ driver.get(reactURL);
+ //Short wait to allow page to download
+ Thread.sleep(SLEEP_DURATION);
+
+ }
+
+
+ @AfterEach
+ public void destroyDriver() {
+ if (driver != null) {
+ //Quit driver
+ driver.close();
+ driver.quit();
+ driver = null;
+ }
+ }
+
+ @Test
+ public void systemTestGradeAssignment() throws Exception {
+ //Input the proper year and semester
+ driver.findElement(By.id("year")).sendKeys("2024");
+ driver.findElement(By.id("semester")).sendKeys("Spring");
+ driver.findElement(By.linkText("Show Sections")).click();
+ Thread.sleep(SLEEP_DURATION);
+
+ //Section 8 should have two assignments
+ WebElement sec8 = driver.findElement(By.id("8"));
+ sec8.findElement(By.linkText("View Assignments")).click();
+ Thread.sleep(SLEEP_DURATION);
+
+ //We will select assignment one to grade.
+ WebElement ass1 = driver.findElement(By.id("1"));
+ ass1.findElements(By.tagName("button")).get(0).click();
+ Thread.sleep(SLEEP_DURATION);
+
+ //We will enter a score of 88 for all students
+ List scoreFields = driver.findElements(By.name("score"));
+
+ for(WebElement field:scoreFields){
+ field.clear();
+ field.sendKeys("88");
+ }
+ driver.findElement(By.id("saveGrades")).click();
+ Thread.sleep(SLEEP_DURATION);
+ String message = driver.findElement(By.id("editMessage")).getText();
+ assertEquals("Grades saved!", message);
+ driver.findElement(By.id("closeGrades")).click();
+
+
+
+ }
+
+ @Test
+ public void systemTestAddAssignment() throws Exception{
+ //Adds an assignment for cst363, Spring 2024
+ driver.findElement(By.id("year")).sendKeys("2024");
+ driver.findElement(By.id("semester")).sendKeys("Spring");
+ driver.findElement(By.linkText("Show Sections")).click();
+ Thread.sleep(SLEEP_DURATION);
+
+ //Check for cst363, view assignments
+ try{
+ while(true){
+ WebElement row363 = driver.findElement(By.xpath("//tr[td='cst363']"));
+ List links = row363.findElements(By.tagName("a"));
+ assertEquals(2, links.size());
+ //View Assignments is the second link
+ links.get(1).click();
+ Thread.sleep(SLEEP_DURATION);
+ }
+ } catch (NoSuchElementException e){
+ //do nothing about it
+ }
+
+ //Add assginment
+ driver.findElement(By.id("addAssignment")).click();
+ Thread.sleep(SLEEP_DURATION);
+
+ //populate data fields
+ driver.findElement(By.id("addTitle")).sendKeys("db assignment 3 [TEST]");
+ WebElement dueDateInput = driver.findElement(By.xpath("//input[@name='dueDate']"));
+ Actions actions = new Actions(driver);
+
+// Click on the input field to activate it
+ actions.moveToElement(dueDateInput).click().perform();
+
+// Send the year
+
+
+// Move the cursor to the month section
+ actions.sendKeys(Keys.LEFT).perform();
+ actions.sendKeys(Keys.LEFT).perform();
+ actions.sendKeys("02").perform();
+ actions.sendKeys("22").perform();
+ actions.sendKeys("2024").perform();
+ actions.sendKeys(Keys.TAB).perform();
+ driver.findElement(By.id("save")).click();
+ Thread.sleep(SLEEP_DURATION);
+
+ //Check to see if the assignment was added then delete
+ WebElement row363 = driver.findElement(By.xpath("//tr[td='db assignment 3 [TEST]']"));
+ List buttons = row363.findElements(By.tagName("button"));
+ assertEquals(3, buttons.size());
+ buttons.get(2).click();
+ Thread.sleep(SLEEP_DURATION);
+ List confirmButtons = driver
+ .findElement(By.className("react-confirm-alert-button-group"))
+ .findElements(By.tagName("button"));
+ assertEquals(2, confirmButtons.size());
+ confirmButtons.get(0).click();
+ Thread.sleep(SLEEP_DURATION);
+
+ //Check to make sure the assignment is deleted
+ assertThrows(NoSuchElementException.class, () ->
+ driver.findElement(By.xpath("//tr[td='db assignment 3 [TEST]']")));
+ }
+
+}
diff --git a/src/test/java/com/cst438/controller/AssignmentControllerUnitTest.java b/src/test/java/com/cst438/controller/AssignmentControllerUnitTest.java
new file mode 100644
index 0000000..330afeb
--- /dev/null
+++ b/src/test/java/com/cst438/controller/AssignmentControllerUnitTest.java
@@ -0,0 +1,297 @@
+package com.cst438.controller;
+
+import com.cst438.domain.*;
+import com.cst438.dto.AssignmentDTO;
+import com.cst438.dto.GradeDTO;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.type.TypeFactory;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.MediaType;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+
+import java.sql.Date;
+import java.util.ArrayList;
+import java.util.List;
+
+import static java.util.stream.Collectors.toList;
+import static org.junit.jupiter.api.Assertions.*;
+
+@AutoConfigureMockMvc
+@SpringBootTest
+public class AssignmentControllerUnitTest {
+
+ @Autowired
+ MockMvc mvc;
+
+ @Autowired
+ SectionRepository sectionRepository;
+
+ @Autowired
+ AssignmentRepository assignmentRepository;
+
+ @Autowired
+ TermRepository termRepository;
+
+ @Autowired
+ CourseRepository courseRepository;
+
+ @Test
+ public void addAssignment() throws Exception {
+ MockHttpServletResponse response;
+
+ // Create DTO with data for new assignment
+ AssignmentDTO assignment = new AssignmentDTO(
+ 0,
+ "Final Project",
+ "2024-05-01",
+ "cst363",
+ 1,
+ 9
+ );
+
+ // Issue an HTTP POST request to add the assignment
+ response = mvc.perform(
+ MockMvcRequestBuilders
+ .post("/assignments")
+ .accept(MediaType.APPLICATION_JSON)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(asJsonString(assignment)))
+ .andReturn()
+ .getResponse();
+
+ // Check the response code for 200 meaning OK
+ assertEquals(200, response.getStatus());
+
+ // Return data converted from String to DTO
+ AssignmentDTO result = fromJsonString(response.getContentAsString(), AssignmentDTO.class);
+
+ // Primary key should have a non-zero value from the database
+ assertNotEquals(0, result.id());
+
+ Assignment a = assignmentRepository.findById(result.id()).orElse(null);
+ assertNotNull(a);
+ Date expectedDate = new Date(124, 4, 1);
+ assertEquals("Final Project", a.getTitle());
+ assertEquals(expectedDate, a.getDueDate());
+
+ // Clean up after test. Issue HTTP DELETE request for assignment
+ response = mvc.perform(
+ MockMvcRequestBuilders
+ .delete("/assignments/" + result.id()))
+ .andReturn()
+ .getResponse();
+
+ assertEquals(200, response.getStatus());
+
+ a = assignmentRepository.findById(result.id()).orElse(null);
+ assertNull(a);
+ }
+
+ @Test
+ public void addAssignmentFailsDueDatePastEndDate() throws Exception {
+ MockHttpServletResponse response;
+
+ AssignmentDTO assignment = new AssignmentDTO(
+ 0,
+ "Final Project",
+ "2024-05-20",
+ "cst363",
+ 1,
+ 9
+ );
+
+ // Issue an HTTP POST request to add the assignment
+ response = mvc.perform(
+ MockMvcRequestBuilders
+ .post("/assignments")
+ .accept(MediaType.APPLICATION_JSON)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(asJsonString(assignment)))
+ .andReturn()
+ .getResponse();
+
+ // Response should be 404, NOT_FOUND
+ assertEquals(404, response.getStatus());
+
+ // Check the expected error message
+ String message = response.getErrorMessage();
+ assertEquals("DueDate is after course EndDate ", message);
+ }
+
+ @Test
+ public void addAssignmentFailsBadSection() throws Exception {
+ MockHttpServletResponse response;
+
+
+ //Section 58 isn't valid
+ AssignmentDTO assignment = new AssignmentDTO(
+ 0,
+ "Integers: What are they?",
+ "2024-05-20",
+ "cst363",
+ 1,
+ 58
+ );
+
+ // The post request, and the response
+ response = mvc.perform(
+ MockMvcRequestBuilders
+ .post("/assignments")
+ .accept(MediaType.APPLICATION_JSON)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(asJsonString(assignment)))
+ .andReturn()
+ .getResponse();
+
+ // We should get a NOT_FOUND 404 error
+ assertEquals(404, response.getStatus());
+
+ // Checking the message returned
+ assertEquals("section not found 58", response.getErrorMessage());
+ }
+
+ //Instructor grades an assignment and uploads
+ @Test
+ public void gradeAssignmentForEnrolled() throws Exception {
+ MockHttpServletResponse responseFromGet;
+ MockHttpServletResponse responseFromPut;
+
+ String getUrl = "/assignments/2/grades";
+ responseFromGet = mvc.perform(
+ MockMvcRequestBuilders
+ .get(getUrl))
+ .andReturn()
+ .getResponse();
+
+ //Check the response code for our get request
+ assertEquals(200, responseFromGet.getStatus());
+
+ //Map response to GradeDTO object list
+ ObjectMapper objectMapper = new ObjectMapper();
+ List gradeDTOS = objectMapper.readValue(
+ responseFromGet.getContentAsString(),
+ TypeFactory.defaultInstance().constructCollectionType(List.class, GradeDTO.class));
+
+ //Set score on returned grades
+ List returnGrades = new ArrayList<>();
+ for(GradeDTO grade: gradeDTOS){
+ GradeDTO newGrade = new GradeDTO(
+ grade.gradeId(),
+ grade.studentName(),
+ grade.studentEmail(),
+ grade.assignmentTitle(),
+ grade.courseId(),
+ grade.sectionId(),
+ 95
+ );
+ returnGrades.add(newGrade);
+
+ };
+ //Send put request for updated grades
+ responseFromPut = mvc.perform(
+ MockMvcRequestBuilders
+ .put("/grades")
+ .accept(MediaType.APPLICATION_JSON)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(asJsonString(returnGrades)))
+ .andReturn()
+ .getResponse();
+
+ //Check that response from put is 200
+ assertEquals(200, responseFromPut.getStatus());
+
+ responseFromGet = mvc.perform(
+ MockMvcRequestBuilders
+ .get(getUrl))
+ .andReturn()
+ .getResponse();
+
+ List updatedGrades = objectMapper.readValue(
+ responseFromGet.getContentAsString(),
+ TypeFactory.defaultInstance().constructCollectionType(List.class, GradeDTO.class));
+
+ //Check that the grades in the database match our updated list
+ assertEquals(returnGrades, updatedGrades);
+
+ //Check that there was an actual update to the grades
+ assertNotEquals(gradeDTOS, updatedGrades);
+
+ //Set grades back to original state
+ responseFromPut = mvc.perform(
+ MockMvcRequestBuilders
+ .put("/grades")
+ .accept(MediaType.APPLICATION_JSON)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(asJsonString(gradeDTOS)))
+ .andReturn()
+ .getResponse();
+ //Check that put worked
+ assertEquals(200, responseFromPut.getStatus());
+
+ responseFromGet = mvc.perform(
+ MockMvcRequestBuilders
+ .get(getUrl))
+ .andReturn()
+ .getResponse();
+
+ List resetGrades = objectMapper.readValue(
+ responseFromGet.getContentAsString(),
+ TypeFactory.defaultInstance().constructCollectionType(List.class, GradeDTO.class));
+
+ //Check that grades now match original state
+ assertEquals(gradeDTOS, resetGrades);
+ }
+
+ @Test
+ public void gradeAssignmentButAssignmentIdInvalid() throws Exception {
+ MockHttpServletResponse response;
+
+ //create assignment with invalid assignmentId
+ AssignmentDTO assignment = new AssignmentDTO(
+ 10,
+ "Final Project",
+ "2024-05-20",
+ "cst363",
+ 1,
+ 9
+ );
+
+ // Issue an HTTP POST request to add the assignment
+ response = mvc.perform(
+ MockMvcRequestBuilders
+ .get("/assignments/"+assignment.id()+"/grades")
+ .accept(MediaType.APPLICATION_JSON)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(asJsonString(assignment)))
+ .andReturn()
+ .getResponse();
+
+ // Response should be 404, NOT_FOUND
+ assertEquals(404, response.getStatus());
+
+ // Check the expected error message
+ String message = response.getErrorMessage();
+ assertEquals("assignment not found "+assignment.id(), message);
+ }
+
+ private static String asJsonString(final Object obj) {
+ try {
+ return new ObjectMapper().writeValueAsString(obj);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static T fromJsonString(String str, Class valueType) {
+ try {
+ return new ObjectMapper().readValue(str, valueType);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/src/test/java/com/cst438/controller/EnrollmentControllerSystemTest.java b/src/test/java/com/cst438/controller/EnrollmentControllerSystemTest.java
new file mode 100644
index 0000000..1ab91f8
--- /dev/null
+++ b/src/test/java/com/cst438/controller/EnrollmentControllerSystemTest.java
@@ -0,0 +1,85 @@
+package com.cst438.controller;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.openqa.selenium.*;
+import org.openqa.selenium.chrome.ChromeDriver;
+import org.openqa.selenium.chrome.ChromeOptions;
+import org.openqa.selenium.interactions.Actions;
+import org.openqa.selenium.support.ui.ExpectedConditions;
+import org.openqa.selenium.support.ui.WebDriverWait;
+
+import java.time.Duration;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class EnrollmentControllerSystemTest {
+
+ public static final String CHROME_DRIVER_FILE_LOCATION =
+ "C:/chromedriver-win64/chromedriver.exe";
+
+ //public static final String CHROME_DRIVER_FILE_LOCATION =
+ // "~/chromedriver_macOS/chromedriver";
+
+ public static final String URL = "http://localhost:3000/";
+ public static final int SLEEP_DURATION = 1000; // 1 second.
+ WebDriver driver;
+
+ // these tests assumes that test data does NOT contain any
+ // sections for course cst499 in 2024 Spring term.
+
+ @BeforeEach
+ public void setUpDriver() throws Exception {
+ // set properties required by Chrome Driver
+ System.setProperty(
+ "webdriver.chrome.driver", CHROME_DRIVER_FILE_LOCATION);
+ ChromeOptions ops = new ChromeOptions();
+ ops.addArguments("--remote-allow-origins=*");
+
+ // start the driver
+ driver = new ChromeDriver(ops);
+
+ driver.get(URL);
+ // must have a short wait to allow time for the page to download
+ Thread.sleep(SLEEP_DURATION);
+ }
+ @AfterEach
+ public void terminateDriver() {
+ if (driver != null) {
+ // quit driver
+ driver.close();
+ driver.quit();
+ driver = null;
+ }
+ }
+
+ @Test
+ public void systemTestEnterFinalGrade() throws Exception {
+ //Input the proper year and semester
+ driver.findElement(By.id("year")).sendKeys("2024");
+ driver.findElement(By.id("semester")).sendKeys("Spring");
+ driver.findElement(By.linkText("Show Sections")).click();
+ Thread.sleep(SLEEP_DURATION);
+
+ //Enter section #8
+ WebElement sec8 = driver.findElement(By.id("8"));
+ sec8.findElement(By.linkText("View Enrollments")).click();
+ Thread.sleep(SLEEP_DURATION);
+
+ //change grade for all students
+ List changeGradeButt = driver.findElements(By.name("changer"));
+ for(WebElement changeGrade:changeGradeButt){
+ changeGrade.click();
+ WebElement field = driver.findElement(By.name("grade"));
+ field.clear();
+ field.sendKeys("C");
+ driver.findElement(By.name("saver")).click();
+ }
+ Thread.sleep(SLEEP_DURATION);
+
+ String message = driver.findElement(By.name("messager")).getText();
+ assertEquals("Grade saved", message);
+
+ }
+}
diff --git a/src/test/java/com/cst438/controller/EnrollmentControllerUnitTest.java b/src/test/java/com/cst438/controller/EnrollmentControllerUnitTest.java
new file mode 100644
index 0000000..6bc2c51
--- /dev/null
+++ b/src/test/java/com/cst438/controller/EnrollmentControllerUnitTest.java
@@ -0,0 +1,105 @@
+package com.cst438.controller;
+
+import java.util.ArrayList;
+import java.util.List;
+import com.cst438.domain.*;
+import com.cst438.dto.AssignmentDTO;
+import com.cst438.dto.EnrollmentDTO;
+import com.cst438.dto.SectionDTO;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.MediaType;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+
+import java.sql.Date;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@AutoConfigureMockMvc
+@SpringBootTest
+public class EnrollmentControllerUnitTest {
+
+ @Autowired
+ MockMvc mvc;
+
+ @Autowired
+ SectionRepository sectionRepository;
+
+ @Autowired
+ AssignmentRepository assignmentRepository;
+
+ @Autowired
+ TermRepository termRepository;
+
+ @Autowired
+ CourseRepository courseRepository;
+
+ @Autowired
+ EnrollmentRepository enrollmentRepository;
+
+ @Test
+ public void enterFinalClassGradesForAll() throws Exception{
+ MockHttpServletResponse response;
+
+ // Create DTO with data for new assignment
+ EnrollmentDTO enrollment0 = new EnrollmentDTO(
+ 1,
+ "B",
+ 3,
+ "thomas edison",
+ "tedison@csumb.edu",
+ "cst363",
+ 9,
+ 9,
+ "052",
+ "104",
+ "M W 10:00-11:50",
+ 4,
+ 2024,
+ "Spring"
+ );
+
+ Listenrollments = new ArrayList<>();
+ enrollments.add(enrollment0);
+
+
+
+ // issue a http POST request to SpringTestServer
+ // specify MediaType for request and response data
+ // convert section to String data and set as request content
+ response = mvc.perform(
+ MockMvcRequestBuilders
+ .put("/enrollments")
+ .accept(MediaType.APPLICATION_JSON)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(asJsonString(enrollments)))
+ .andReturn()
+ .getResponse();
+
+ // check the response code for 200 meaning OK
+ assertEquals(200, response.getStatus());
+
+
+ }
+
+ private static String asJsonString(final Object obj) {
+ try {
+ return new ObjectMapper().writeValueAsString(obj);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static T fromJsonString(String str, Class valueType ) {
+ try {
+ return new ObjectMapper().readValue(str, valueType);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/src/test/java/com/cst438/controller/SectionControllerSystemTest.java b/src/test/java/com/cst438/controller/SectionControllerSystemTest.java
index 006b969..61bf082 100644
--- a/src/test/java/com/cst438/controller/SectionControllerSystemTest.java
+++ b/src/test/java/com/cst438/controller/SectionControllerSystemTest.java
@@ -18,7 +18,7 @@ public class SectionControllerSystemTest {
// for WinOS the file name will be chromedriver.exe
// for MacOS the file name will be chromedriver
public static final String CHROME_DRIVER_FILE_LOCATION =
- "C:/chromedriver_win32/chromedriver.exe";
+ "C:/chromedriver_win64/chromedriver.exe";
//public static final String CHROME_DRIVER_FILE_LOCATION =
// "~/chromedriver_macOS/chromedriver";
diff --git a/src/test/java/com/cst438/controller/SectionControllerUnitTest.java b/src/test/java/com/cst438/controller/SectionControllerUnitTest.java
index 0d3844e..7f8f2e2 100644
--- a/src/test/java/com/cst438/controller/SectionControllerUnitTest.java
+++ b/src/test/java/com/cst438/controller/SectionControllerUnitTest.java
@@ -122,7 +122,7 @@ public void addSectionFailsBadCourse( ) throws Exception {
.getResponse();
// response should be 400, BAD_REQUEST
- assertEquals(400, response.getStatus());
+ assertEquals(404, response.getStatus());
// check the expected error message
String message = response.getErrorMessage();
diff --git a/src/test/java/com/cst438/controller/StudentControllerSystemTest.java b/src/test/java/com/cst438/controller/StudentControllerSystemTest.java
new file mode 100644
index 0000000..d1da47b
--- /dev/null
+++ b/src/test/java/com/cst438/controller/StudentControllerSystemTest.java
@@ -0,0 +1,114 @@
+//note: requires user to be STUDENT
+
+package com.cst438.controller;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.openqa.selenium.*;
+import org.openqa.selenium.chrome.ChromeDriver;
+import org.openqa.selenium.chrome.ChromeOptions;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class StudentControllerSystemTest {
+
+ public static final String CHROME_DRIVER_FILE_LOCATION =
+ "./chromedriver";
+
+ //public static final String CHROME_DRIVER_FILE_LOCATION =
+ // "~/chromedriver_macOS/chromedriver";
+ public static final String URL = "http://localhost:3000/";
+
+ public static final int SLEEP_DURATION = 1000; // 1 second.
+
+ // add selenium dependency to pom.xml
+
+ // these tests assumes that test data does NOT contain any
+ // sections for course cst499 in 2024 Spring term.
+
+ WebDriver driver;
+
+ @BeforeEach
+ public void setUpDriver() throws Exception {
+
+ // set properties required by Chrome Driver
+ System.setProperty(
+ "webdriver.chrome.driver", CHROME_DRIVER_FILE_LOCATION);
+ ChromeOptions ops = new ChromeOptions();
+ ops.addArguments("--remote-allow-origins=*");
+
+ // start the driver
+ driver = new ChromeDriver(ops);
+
+ driver.get(URL);
+ // must have a short wait to allow time for the page to download
+ Thread.sleep(SLEEP_DURATION);
+
+ }
+
+ @AfterEach
+ public void terminateDriver() {
+ if (driver != null) {
+ // quit driver
+ driver.close();
+ driver.quit();
+ driver = null;
+ }
+ }
+
+ @Test
+ public void systemTestEnrollSection() throws Exception {
+ // add first available section
+ // verify enrollment appears on schedule
+ // drop course
+
+ //click link to navigate to course enroll
+ WebElement we = driver.findElement(By.id("addCourse"));
+ we.click();
+ Thread.sleep(SLEEP_DURATION);
+
+ //connect driver to buttons
+ List buttons = driver.findElements(By.tagName("button"));
+
+ //consider clicking each available section
+// for (WebElement button : buttons) {
+// button.click();
+// Thread.sleep(SLEEP_DURATION);
+// }
+
+ //click to enroll in first available section
+ buttons.get(0).click();
+ Thread.sleep(SLEEP_DURATION);
+
+ String message = driver.findElement(By.id("addMessage")).getText();
+ //assertTrue(message.equals("course added"));
+ assertEquals("course added", message);
+
+ we = driver.findElement(By.id("schedule"));
+ we.click();
+ driver.findElement(By.id("ayear")).sendKeys("2024");
+ driver.findElement(By.id("asemester")).sendKeys("Spring");
+ driver.findElement(By.id("search")).click();
+ Thread.sleep(SLEEP_DURATION);
+
+ //drop recently added section from CST338
+ WebElement row = driver.findElement(By.xpath("//tr[td='cst338']"));
+ assertNotNull(row);
+
+ WebElement dropButton = row.findElement(By.tagName("button"));
+ dropButton.click();
+ Thread.sleep(SLEEP_DURATION);
+
+ // find the YES to confirm button
+ List confirmButtons = driver
+ .findElement(By.className("react-confirm-alert-button-group"))
+ .findElements(By.tagName("button"));
+ assertEquals(2,confirmButtons.size());
+ confirmButtons.get(0).click();
+ Thread.sleep(SLEEP_DURATION);
+
+ }
+}
diff --git a/src/test/java/com/cst438/controller/StudentControllerUnitTest.java b/src/test/java/com/cst438/controller/StudentControllerUnitTest.java
new file mode 100644
index 0000000..511aa91
--- /dev/null
+++ b/src/test/java/com/cst438/controller/StudentControllerUnitTest.java
@@ -0,0 +1,250 @@
+package com.cst438.controller;
+
+import com.cst438.domain.*;
+import com.cst438.dto.AssignmentDTO;
+import com.cst438.dto.EnrollmentDTO;
+import com.cst438.dto.SectionDTO;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.MediaType;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+
+import java.sql.Date;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@AutoConfigureMockMvc
+@SpringBootTest
+public class StudentControllerUnitTest {
+
+ @Autowired
+ MockMvc mvc;
+
+ @Autowired
+ SectionRepository sectionRepository;
+
+ @Autowired
+ AssignmentRepository assignmentRepository;
+
+ @Autowired
+ TermRepository termRepository;
+
+ @Autowired
+ CourseRepository courseRepository;
+
+ @Autowired
+ EnrollmentRepository enrollmentRepository;
+
+ @Test
+ public void enrollInSection() throws Exception {
+ MockHttpServletResponse response;
+
+ // Create DTO with data for new assignment
+ EnrollmentDTO enrollment = new EnrollmentDTO(
+ 0,
+ "A",
+ 3,
+ "thomas edison",
+ "tedison@csumb.edu",
+ "cst363",
+ 9,
+ 9,
+ "052",
+ "104",
+ "M W 10:00-11:50",
+ 4,
+ 2024,
+ "Spring"
+ );
+
+ // issue a http POST request to SpringTestServer
+ // specify MediaType for request and response data
+ // convert section to String data and set as request content
+ response = mvc.perform(
+ MockMvcRequestBuilders
+ .post("/enrollments/sections/"+enrollment.sectionNo()+"?studentId="+enrollment.studentId())
+ .accept(MediaType.APPLICATION_JSON)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(asJsonString(enrollment)))
+ .andReturn()
+ .getResponse();
+
+ // check the response code for 200 meaning OK
+ assertEquals(200, response.getStatus());
+
+ // return data converted from String to DTO
+ EnrollmentDTO result = fromJsonString(response.getContentAsString(), EnrollmentDTO.class);
+
+ // primary key should have a non zero value from the database
+ assertNotEquals(0, result.enrollmentId());
+ // check other fields of the DTO for expected values
+ assertEquals("cst363", result.courseId());
+
+ // check the database
+ Enrollment e = enrollmentRepository.findById(result.enrollmentId()).orElse(null);
+ assertNotNull(e);
+ assertEquals("cst363", e.getSection().getCourse().getCourseId());
+
+ // clean up after test. issue http DELETE request for section
+ response = mvc.perform(
+ MockMvcRequestBuilders
+ .delete("/enrollments/"+result.enrollmentId()))
+ .andReturn()
+ .getResponse();
+
+ assertEquals(200, response.getStatus());
+
+ // check database for delete
+ e = enrollmentRepository.findById(result.enrollmentId()).orElse(null);
+ //s = sectionRepository.findById(result.secNo()).orElse(null);
+ assertNull(e); // section should not be found after delete
+ }
+
+ @Test
+ public void enrollInSectionButAlreadyEnrolled() throws Exception {
+ MockHttpServletResponse response;
+
+ // Create DTO with data for new assignment
+ EnrollmentDTO enrollment = new EnrollmentDTO(
+ 0,
+ "A",
+ 3,
+ "thomas edison",
+ "tedison@csumb.edu",
+ "cst363",
+ 1,
+ 8,
+ "052",
+ "104",
+ "M W 10:00-11:50",
+ 4,
+ 2024,
+ "Spring"
+ );
+
+ // issue a http POST request to SpringTestServer
+ // specify MediaType for request and response data
+ // convert section to String data and set as request content
+ response = mvc.perform(
+ MockMvcRequestBuilders
+ .post("/enrollments/sections/"+enrollment.sectionNo()+"?studentId="+enrollment.studentId())
+ .accept(MediaType.APPLICATION_JSON)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(asJsonString(enrollment)))
+ .andReturn()
+ .getResponse();
+
+ // check the response code for 200 meaning OK
+ assertEquals(400, response.getStatus());
+
+ // check the expected error message
+ String message = response.getErrorMessage();
+ assertEquals("already enrolled in this section", message);
+ }
+
+ @Test
+ public void enrollinSectionButInvalidSectionNo() throws Exception{
+ MockHttpServletResponse response;
+
+ // Create DTO with data for new assignment
+ EnrollmentDTO enrollment = new EnrollmentDTO(
+ 0,
+ "A",
+ 3,
+ "thomas edison",
+ "tedison@csumb.edu",
+ "cst363",
+ 1,
+ 58,
+ "052",
+ "104",
+ "M W 10:00-11:50",
+ 4,
+ 2024,
+ "Spring"
+ );
+
+ // issue a http POST request to SpringTestServer
+ // specify MediaType for request and response data
+ // convert section to String data and set as request content
+ response = mvc.perform(
+ MockMvcRequestBuilders
+ .post("/enrollments/sections/"+enrollment.sectionNo()+"?studentId="+enrollment.studentId())
+ .accept(MediaType.APPLICATION_JSON)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(asJsonString(enrollment)))
+ .andReturn()
+ .getResponse();
+
+ // We should get a NOT_FOUND 404 error
+ assertEquals(404, response.getStatus());
+
+ // check the expected error message
+ String message = response.getErrorMessage();
+ assertEquals("section not found 58", message);
+
+ }
+
+ @Test
+ public void enrollinSectionButPastDeadline() throws Exception{
+ MockHttpServletResponse response;
+
+ // Create DTO with data for new assignment
+ EnrollmentDTO enrollment = new EnrollmentDTO(
+ 0,
+ "A",
+ 3,
+ "thomas edison",
+ "tedison@csumb.edu",
+ "cst338",
+ 1,
+ 1,
+ "052",
+ "100",
+ "M W 10:00-11:50",
+ 4,
+ 2024,
+ "Spring"
+ );
+
+ // issue a http POST request to SpringTestServer
+ // specify MediaType for request and response data
+ // convert section to String data and set as request content
+ response = mvc.perform(
+ MockMvcRequestBuilders
+ .post("/enrollments/sections/"+enrollment.sectionNo()+"?studentId="+enrollment.studentId())
+ .accept(MediaType.APPLICATION_JSON)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(asJsonString(enrollment)))
+ .andReturn()
+ .getResponse();
+
+ // check the response code for 200 meaning OK
+ assertEquals(400, response.getStatus());
+
+ // check the expected error message
+ String message = response.getErrorMessage();
+ assertEquals("Invalid date", message);
+ }
+
+ private static String asJsonString(final Object obj) {
+ try {
+ return new ObjectMapper().writeValueAsString(obj);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static T fromJsonString(String str, Class valueType ) {
+ try {
+ return new ObjectMapper().readValue(str, valueType);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+}