CoursesController.java

1
package edu.ucsb.cs156.frontiers.controllers;
2
3
import com.fasterxml.jackson.core.JsonProcessingException;
4
import edu.ucsb.cs156.frontiers.entities.Course;
5
import edu.ucsb.cs156.frontiers.entities.CourseStaff;
6
import edu.ucsb.cs156.frontiers.entities.RosterStudent;
7
import edu.ucsb.cs156.frontiers.entities.User;
8
import edu.ucsb.cs156.frontiers.enums.OrgStatus;
9
import edu.ucsb.cs156.frontiers.errors.EntityNotFoundException;
10
import edu.ucsb.cs156.frontiers.errors.InvalidInstallationTypeException;
11
import edu.ucsb.cs156.frontiers.models.CurrentUser;
12
import edu.ucsb.cs156.frontiers.repositories.AdminRepository;
13
import edu.ucsb.cs156.frontiers.repositories.CourseRepository;
14
import edu.ucsb.cs156.frontiers.repositories.CourseStaffRepository;
15
import edu.ucsb.cs156.frontiers.repositories.InstructorRepository;
16
import edu.ucsb.cs156.frontiers.repositories.RosterStudentRepository;
17
import edu.ucsb.cs156.frontiers.repositories.UserRepository;
18
import edu.ucsb.cs156.frontiers.services.OrganizationLinkerService;
19
import edu.ucsb.cs156.frontiers.utilities.CanonicalFormConverter;
20
import io.swagger.v3.oas.annotations.Operation;
21
import io.swagger.v3.oas.annotations.Parameter;
22
import io.swagger.v3.oas.annotations.tags.Tag;
23
import java.security.NoSuchAlgorithmException;
24
import java.security.spec.InvalidKeySpecException;
25
import java.util.ArrayList;
26
import java.util.List;
27
import java.util.Map;
28
import java.util.Optional;
29
import java.util.stream.Collectors;
30
import lombok.extern.slf4j.Slf4j;
31
import org.springframework.beans.factory.annotation.Autowired;
32
import org.springframework.http.HttpHeaders;
33
import org.springframework.http.HttpStatus;
34
import org.springframework.http.ResponseEntity;
35
import org.springframework.security.access.prepost.PreAuthorize;
36
import org.springframework.web.bind.annotation.*;
37
38
@Tag(name = "Course")
39
@RequestMapping("/api/courses")
40
@RestController
41
@Slf4j
42
public class CoursesController extends ApiController {
43
44
  @Autowired private CourseRepository courseRepository;
45
46
  @Autowired private UserRepository userRepository;
47
48
  @Autowired private RosterStudentRepository rosterStudentRepository;
49
50
  @Autowired private CourseStaffRepository courseStaffRepository;
51
52
  @Autowired private InstructorRepository instructorRepository;
53
54
  @Autowired private AdminRepository adminRepository;
55
56
  @Autowired private OrganizationLinkerService linkerService;
57
58
  /**
59
   * This method creates a new Course.
60
   *
61
   * @param courseName the name of the course
62
   * @param term the term of the course
63
   * @param school the school of the course
64
   * @return the created course
65
   */
66
  @Operation(summary = "Create a new course")
67
  @PreAuthorize("hasRole('ROLE_ADMIN') || hasRole('ROLE_INSTRUCTOR')")
68
  @PostMapping("/post")
69
  public InstructorCourseView postCourse(
70
      @Parameter(name = "courseName") @RequestParam String courseName,
71
      @Parameter(name = "term") @RequestParam String term,
72
      @Parameter(name = "school") @RequestParam String school) {
73
    // get current date right now and set status to pending
74
    CurrentUser currentUser = getCurrentUser();
75
    Course course =
76
        Course.builder()
77
            .courseName(courseName)
78
            .term(term)
79
            .school(school)
80
            .instructorEmail(currentUser.getUser().getEmail())
81
            .build();
82
    Course savedCourse = courseRepository.save(course);
83
84 1 1. postCourse : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::postCourse → KILLED
    return new InstructorCourseView(savedCourse);
85
  }
86
87
  /** Projection of Course entity with fields that are relevant for instructors and admins */
88
  public static record InstructorCourseView(
89
      Long id,
90
      String installationId,
91
      String orgName,
92
      String courseName,
93
      String term,
94
      String school,
95
      String instructorEmail,
96
      int numStudents,
97
      int numStaff) {
98
99
    // Creates view from Course entity
100
    public InstructorCourseView(Course c) {
101
      this(
102
          c.getId(),
103
          c.getInstallationId(),
104
          c.getOrgName(),
105
          c.getCourseName(),
106
          c.getTerm(),
107
          c.getSchool(),
108
          c.getInstructorEmail(),
109 1 1. <init> : negated conditional → KILLED
          c.getRosterStudents() != null ? c.getRosterStudents().size() : 0,
110 1 1. <init> : negated conditional → KILLED
          c.getCourseStaff() != null ? c.getCourseStaff().size() : 0);
111
    }
112
  }
113
114
  /**
115
   * This method returns a list of courses.
116
   *
117
   * @return a list of all courses for an instructor.
118
   */
119
  @Operation(summary = "List all courses for an instructor")
120
  @PreAuthorize("hasRole('ROLE_INSTRUCTOR')")
121
  @GetMapping("/allForInstructors")
122
  public Iterable<InstructorCourseView> allForInstructors() {
123
    CurrentUser currentUser = getCurrentUser();
124
    String instructorEmail = currentUser.getUser().getEmail();
125
    List<Course> courses = courseRepository.findByInstructorEmail(instructorEmail);
126
127
    List<InstructorCourseView> courseViews =
128
        courses.stream().map(InstructorCourseView::new).collect(Collectors.toList());
129 1 1. allForInstructors : replaced return value with Collections.emptyList for edu/ucsb/cs156/frontiers/controllers/CoursesController::allForInstructors → KILLED
    return courseViews;
130
  }
131
132
  /**
133
   * This method returns a list of courses.
134
   *
135
   * @return a list of all courses for an admin.
136
   */
137
  @Operation(summary = "List all courses for an admin")
138
  @PreAuthorize("hasRole('ROLE_ADMIN')")
139
  @GetMapping("/allForAdmins")
140
  public Iterable<InstructorCourseView> allForAdmins() {
141
    List<Course> courses = courseRepository.findAll();
142
143
    List<InstructorCourseView> courseViews =
144
        courses.stream().map(InstructorCourseView::new).collect(Collectors.toList());
145 1 1. allForAdmins : replaced return value with Collections.emptyList for edu/ucsb/cs156/frontiers/controllers/CoursesController::allForAdmins → KILLED
    return courseViews;
146
  }
147
148
  /**
149
   * This method returns single course by its id
150
   *
151
   * @return a course
152
   */
153
  @Operation(summary = "Get course by id")
154
  @PreAuthorize("@CourseSecurity.hasManagePermissions(#root, #id)")
155
  @GetMapping("/{id}")
156
  public InstructorCourseView getCourseById(@Parameter(name = "id") @PathVariable Long id) {
157
    Course course =
158
        courseRepository
159
            .findById(id)
160 1 1. lambda$getCourseById$0 : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::lambda$getCourseById$0 → KILLED
            .orElseThrow(() -> new EntityNotFoundException(Course.class, id));
161
    // Convert to InstructorCourseView
162
    InstructorCourseView courseView = new InstructorCourseView(course);
163 1 1. getCourseById : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::getCourseById → KILLED
    return courseView;
164
  }
165
166
  /**
167
   * This is the outgoing method, redirecting from Frontiers to GitHub to allow a Course to be
168
   * linked to a GitHub Organization. It redirects from Frontiers to the GitHub app installation
169
   * process, and will return with the {@link #addInstallation(Optional, String, String, Long)
170
   * addInstallation()} endpoint
171
   *
172
   * @param courseId id of the course to be linked to
173
   * @return dynamically loaded url to install Frontiers to a Github Organization, with the courseId
174
   *     marked as the state parameter, which GitHub will return.
175
   */
176
  @Operation(summary = "Authorize Frontiers to a Github Course")
177
  @PreAuthorize("@CourseSecurity.hasManagePermissions(#root, #courseId)")
178
  @GetMapping("/redirect")
179
  public ResponseEntity<Void> linkCourse(@Parameter Long courseId)
180
      throws JsonProcessingException, NoSuchAlgorithmException, InvalidKeySpecException {
181
    String newUrl = linkerService.getRedirectUrl();
182
    newUrl += "/installations/new?state=" + courseId;
183
    // found this convenient solution here:
184
    // https://stackoverflow.com/questions/29085295/spring-mvc-restcontroller-and-redirect
185 1 1. linkCourse : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::linkCourse → KILLED
    return ResponseEntity.status(HttpStatus.MOVED_PERMANENTLY)
186
        .header(HttpHeaders.LOCATION, newUrl)
187
        .build();
188
  }
189
190
  /**
191
   * @param installation_id id of the incoming GitHub Organization installation
192
   * @param setup_action whether the permissions are installed or updated. Required RequestParam but
193
   *     not used by the method.
194
   * @param code token to be exchanged with GitHub to ensure the request is legitimate and not
195
   *     spoofed.
196
   * @param state id of the Course to be linked with the GitHub installation.
197
   * @return ResponseEntity, returning /success if the course was successfully linked or /noperms if
198
   *     the user does not have the permission to install the application on GitHub. Alternately
199
   *     returns 403 Forbidden if the user is not the creator.
200
   */
201
  @Operation(summary = "Link a Course to a Github Organization by installing Github App")
202
  @PreAuthorize("hasRole('ROLE_ADMIN') || hasRole('ROLE_INSTRUCTOR')")
203
  @GetMapping("link")
204
  public ResponseEntity<Void> addInstallation(
205
      @Parameter(name = "installationId") @RequestParam Optional<String> installation_id,
206
      @Parameter(name = "setupAction") @RequestParam String setup_action,
207
      @Parameter(name = "code") @RequestParam String code,
208
      @Parameter(name = "state") @RequestParam Long state)
209
      throws NoSuchAlgorithmException, InvalidKeySpecException, JsonProcessingException {
210 1 1. addInstallation : negated conditional → KILLED
    if (installation_id.isEmpty()) {
211 1 1. addInstallation : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::addInstallation → KILLED
      return ResponseEntity.status(HttpStatus.MOVED_PERMANENTLY)
212
          .header(HttpHeaders.LOCATION, "/courses/nopermissions")
213
          .build();
214
    } else {
215
      Course course =
216
          courseRepository
217
              .findById(state)
218 1 1. lambda$addInstallation$1 : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::lambda$addInstallation$1 → KILLED
              .orElseThrow(() -> new EntityNotFoundException(Course.class, state));
219 1 1. addInstallation : negated conditional → KILLED
      if (!isCurrentUserAdmin()
220 1 1. addInstallation : negated conditional → KILLED
          && !course.getInstructorEmail().equals(getCurrentUser().getUser().getEmail())) {
221 1 1. addInstallation : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::addInstallation → KILLED
        return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
222
      } else {
223
        String orgName = linkerService.getOrgName(installation_id.get());
224 1 1. addInstallation : removed call to edu/ucsb/cs156/frontiers/entities/Course::setInstallationId → KILLED
        course.setInstallationId(installation_id.get());
225 1 1. addInstallation : removed call to edu/ucsb/cs156/frontiers/entities/Course::setOrgName → KILLED
        course.setOrgName(orgName);
226
        course
227
            .getRosterStudents()
228 1 1. addInstallation : removed call to java/util/List::forEach → KILLED
            .forEach(
229
                rs -> {
230 1 1. lambda$addInstallation$2 : removed call to edu/ucsb/cs156/frontiers/entities/RosterStudent::setOrgStatus → KILLED
                  rs.setOrgStatus(OrgStatus.JOINCOURSE);
231
                });
232
        course
233
            .getCourseStaff()
234 1 1. addInstallation : removed call to java/util/List::forEach → KILLED
            .forEach(
235
                cs -> {
236 1 1. lambda$addInstallation$3 : removed call to edu/ucsb/cs156/frontiers/entities/CourseStaff::setOrgStatus → KILLED
                  cs.setOrgStatus(OrgStatus.JOINCOURSE);
237
                });
238
        courseRepository.save(course);
239 1 1. addInstallation : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::addInstallation → KILLED
        return ResponseEntity.status(HttpStatus.MOVED_PERMANENTLY)
240
            .header(HttpHeaders.LOCATION, "/login/success")
241
            .build();
242
      }
243
    }
244
  }
245
246
  /**
247
   * This method handles the InvalidInstallationTypeException.
248
   *
249
   * @param e the exception
250
   * @return a map with the type and message of the exception
251
   */
252
  @ExceptionHandler({InvalidInstallationTypeException.class})
253
  @ResponseStatus(HttpStatus.BAD_REQUEST)
254
  public Object handleInvalidInstallationType(Throwable e) {
255 1 1. handleInvalidInstallationType : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::handleInvalidInstallationType → KILLED
    return Map.of(
256
        "type", e.getClass().getSimpleName(),
257
        "message", e.getMessage());
258
  }
259
260
  public record RosterStudentCoursesDTO(
261
      Long id,
262
      String installationId,
263
      String orgName,
264
      String courseName,
265
      String term,
266
      String school,
267
      OrgStatus studentStatus,
268
      Long rosterStudentId) {}
269
270
  /**
271
   * This method returns a list of courses that the current user is enrolled.
272
   *
273
   * @return a list of courses in the DTO form along with the student status in the organization.
274
   */
275
  @Operation(summary = "List all courses for the current student, including their org status")
276
  @PreAuthorize("hasRole('ROLE_USER')")
277
  @GetMapping("/list")
278
  public List<RosterStudentCoursesDTO> listCoursesForCurrentUser() {
279
    String email = getCurrentUser().getUser().getEmail();
280
    Iterable<RosterStudent> rosterStudentsIterable = rosterStudentRepository.findAllByEmail(email);
281
    List<RosterStudent> rosterStudents = new ArrayList<>();
282 1 1. listCoursesForCurrentUser : removed call to java/lang/Iterable::forEach → KILLED
    rosterStudentsIterable.forEach(rosterStudents::add);
283 1 1. listCoursesForCurrentUser : replaced return value with Collections.emptyList for edu/ucsb/cs156/frontiers/controllers/CoursesController::listCoursesForCurrentUser → KILLED
    return rosterStudents.stream()
284
        .map(
285
            rs -> {
286
              Course course = rs.getCourse();
287
              RosterStudentCoursesDTO rsDto =
288
                  new RosterStudentCoursesDTO(
289
                      course.getId(),
290
                      course.getInstallationId(),
291
                      course.getOrgName(),
292
                      course.getCourseName(),
293
                      course.getTerm(),
294
                      course.getSchool(),
295
                      rs.getOrgStatus(),
296
                      rs.getId());
297 1 1. lambda$listCoursesForCurrentUser$4 : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::lambda$listCoursesForCurrentUser$4 → KILLED
              return rsDto;
298
            })
299
        .collect(Collectors.toList());
300
  }
301
302
  public record StaffCoursesDTO(
303
      Long id,
304
      String installationId,
305
      String orgName,
306
      String courseName,
307
      String term,
308
      String school,
309
      OrgStatus studentStatus,
310
      Long staffId) {}
311
312
  /**
313
   * student see what courses they appear as staff in
314
   *
315
   * @param studentId the id of the student making request
316
   * @return a list of all courses student is staff in
317
   */
318
  @Operation(summary = "Student see what courses they appear as staff in")
319
  @PreAuthorize("hasRole('ROLE_USER')")
320
  @GetMapping("/staffCourses")
321
  public List<StaffCoursesDTO> staffCourses() {
322
    CurrentUser currentUser = getCurrentUser();
323
    User user = currentUser.getUser();
324
325
    String email = user.getEmail();
326
327
    List<CourseStaff> staffMembers = courseStaffRepository.findAllByEmail(email);
328 1 1. staffCourses : replaced return value with Collections.emptyList for edu/ucsb/cs156/frontiers/controllers/CoursesController::staffCourses → KILLED
    return staffMembers.stream()
329
        .map(
330
            s -> {
331
              Course course = s.getCourse();
332
              StaffCoursesDTO sDto =
333
                  new StaffCoursesDTO(
334
                      course.getId(),
335
                      course.getInstallationId(),
336
                      course.getOrgName(),
337
                      course.getCourseName(),
338
                      course.getTerm(),
339
                      course.getSchool(),
340
                      s.getOrgStatus(),
341
                      s.getId());
342 1 1. lambda$staffCourses$5 : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::lambda$staffCourses$5 → KILLED
              return sDto;
343
            })
344
        .collect(Collectors.toList());
345
  }
346
347
  @Operation(summary = "Update instructor email for a course (admin only)")
348
  @PreAuthorize("hasRole('ROLE_ADMIN')")
349
  @PutMapping("/updateInstructor")
350
  public InstructorCourseView updateInstructorEmail(
351
      @Parameter(name = "courseId") @RequestParam Long courseId,
352
      @Parameter(name = "instructorEmail") @RequestParam String instructorEmail) {
353
354
    Course course =
355
        courseRepository
356
            .findById(courseId)
357 1 1. lambda$updateInstructorEmail$6 : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::lambda$updateInstructorEmail$6 → KILLED
            .orElseThrow(() -> new EntityNotFoundException(Course.class, courseId));
358
359
    String sanitizedEmail = CanonicalFormConverter.convertToValidEmail(instructorEmail);
360
361
    // Validate that the email exists in either instructor or admin table
362
    boolean isInstructor = instructorRepository.existsByEmail(sanitizedEmail);
363
    boolean isAdmin = adminRepository.existsByEmail(sanitizedEmail);
364
365 2 1. updateInstructorEmail : negated conditional → KILLED
2. updateInstructorEmail : negated conditional → KILLED
    if (!isInstructor && !isAdmin) {
366
      throw new IllegalArgumentException("Email must belong to either an instructor or admin");
367
    }
368
369 1 1. updateInstructorEmail : removed call to edu/ucsb/cs156/frontiers/entities/Course::setInstructorEmail → KILLED
    course.setInstructorEmail(sanitizedEmail);
370
    Course savedCourse = courseRepository.save(course);
371
372 1 1. updateInstructorEmail : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::updateInstructorEmail → KILLED
    return new InstructorCourseView(savedCourse);
373
  }
374
375
  @Operation(summary = "Delete a course")
376
  @PreAuthorize("hasRole('ROLE_ADMIN')")
377
  @DeleteMapping("")
378
  public Object deleteCourse(@RequestParam Long courseId)
379
      throws NoSuchAlgorithmException, InvalidKeySpecException {
380
    Course course =
381
        courseRepository
382
            .findById(courseId)
383 1 1. lambda$deleteCourse$7 : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::lambda$deleteCourse$7 → KILLED
            .orElseThrow(() -> new EntityNotFoundException(Course.class, courseId));
384
385
    // Check if course has roster students or staff
386 2 1. deleteCourse : negated conditional → KILLED
2. deleteCourse : negated conditional → KILLED
    if (!course.getRosterStudents().isEmpty() || !course.getCourseStaff().isEmpty()) {
387
      throw new IllegalArgumentException("Cannot delete course with students or staff");
388
    }
389
390 1 1. deleteCourse : removed call to edu/ucsb/cs156/frontiers/services/OrganizationLinkerService::unenrollOrganization → KILLED
    linkerService.unenrollOrganization(course);
391 1 1. deleteCourse : removed call to edu/ucsb/cs156/frontiers/repositories/CourseRepository::delete → KILLED
    courseRepository.delete(course);
392 1 1. deleteCourse : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::deleteCourse → KILLED
    return genericMessage("Course with id %s deleted".formatted(course.getId()));
393
  }
394
395
  /**
396
   * This method updates an existing course.
397
   *
398
   * @param courseId the id of the course to update
399
   * @param courseName the new name of the course
400
   * @param term the new term of the course
401
   * @param school the new school of the course
402
   * @return the updated course
403
   */
404
  @Operation(summary = "Update an existing course")
405
  @PreAuthorize("@CourseSecurity.hasManagePermissions(#root, #courseId)")
406
  @PutMapping("")
407
  public InstructorCourseView updateCourse(
408
      @Parameter(name = "courseId") @RequestParam Long courseId,
409
      @Parameter(name = "courseName") @RequestParam String courseName,
410
      @Parameter(name = "term") @RequestParam String term,
411
      @Parameter(name = "school") @RequestParam String school) {
412
    Course course =
413
        courseRepository
414
            .findById(courseId)
415 1 1. lambda$updateCourse$8 : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::lambda$updateCourse$8 → KILLED
            .orElseThrow(() -> new EntityNotFoundException(Course.class, courseId));
416
417 1 1. updateCourse : removed call to edu/ucsb/cs156/frontiers/entities/Course::setCourseName → KILLED
    course.setCourseName(courseName);
418 1 1. updateCourse : removed call to edu/ucsb/cs156/frontiers/entities/Course::setTerm → KILLED
    course.setTerm(term);
419 1 1. updateCourse : removed call to edu/ucsb/cs156/frontiers/entities/Course::setSchool → KILLED
    course.setSchool(school);
420
421
    Course savedCourse = courseRepository.save(course);
422
423 1 1. updateCourse : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::updateCourse → KILLED
    return new InstructorCourseView(savedCourse);
424
  }
425
}

Mutations

84

1.1
Location : postCourse
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testPostCourse_byInstructor()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::postCourse → KILLED

109

1.1
Location : <init>
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testInstructorCourseView_withNullRosterStudents()]
negated conditional → KILLED

110

1.1
Location : <init>
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testInstructorCourseView_withNullCourseStaff()]
negated conditional → KILLED

129

1.1
Location : allForInstructors
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testAllCourses_ROLE_INSTRUCTOR()]
replaced return value with Collections.emptyList for edu/ucsb/cs156/frontiers/controllers/CoursesController::allForInstructors → KILLED

145

1.1
Location : allForAdmins
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testAllCourses_ROLE_ADMIN()]
replaced return value with Collections.emptyList for edu/ucsb/cs156/frontiers/controllers/CoursesController::allForAdmins → KILLED

160

1.1
Location : lambda$getCourseById$0
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testGetCourseById_courseDoesNotExist()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::lambda$getCourseById$0 → KILLED

163

1.1
Location : getCourseById
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testGetCourseById()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::getCourseById → KILLED

185

1.1
Location : linkCourse
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testRedirect()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::linkCourse → KILLED

210

1.1
Location : addInstallation
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testNoPerms()]
negated conditional → KILLED

211

1.1
Location : addInstallation
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testNoPerms()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::addInstallation → KILLED

218

1.1
Location : lambda$addInstallation$1
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testCourseLinkNotFound()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::lambda$addInstallation$1 → KILLED

219

1.1
Location : addInstallation
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testCourseLinkSuccessWhenAdminNotCreator()]
negated conditional → KILLED

220

1.1
Location : addInstallation
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testLinkCourseSuccessfullyProfessorCreator()]
negated conditional → KILLED

221

1.1
Location : addInstallation
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testNotCreator()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::addInstallation → KILLED

224

1.1
Location : addInstallation
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testCourseLinkSuccessWhenAdminNotCreator()]
removed call to edu/ucsb/cs156/frontiers/entities/Course::setInstallationId → KILLED

225

1.1
Location : addInstallation
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testCourseLinkSuccessWhenAdminNotCreator()]
removed call to edu/ucsb/cs156/frontiers/entities/Course::setOrgName → KILLED

228

1.1
Location : addInstallation
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testLinkCourseSuccessfully()]
removed call to java/util/List::forEach → KILLED

230

1.1
Location : lambda$addInstallation$2
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testLinkCourseSuccessfully()]
removed call to edu/ucsb/cs156/frontiers/entities/RosterStudent::setOrgStatus → KILLED

234

1.1
Location : addInstallation
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testLinkCourseSuccessfully()]
removed call to java/util/List::forEach → KILLED

236

1.1
Location : lambda$addInstallation$3
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testLinkCourseSuccessfully()]
removed call to edu/ucsb/cs156/frontiers/entities/CourseStaff::setOrgStatus → KILLED

239

1.1
Location : addInstallation
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testCourseLinkSuccessWhenAdminNotCreator()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::addInstallation → KILLED

255

1.1
Location : handleInvalidInstallationType
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testNotOrganization()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::handleInvalidInstallationType → KILLED

282

1.1
Location : listCoursesForCurrentUser
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testListCoursesForCurrentUser()]
removed call to java/lang/Iterable::forEach → KILLED

283

1.1
Location : listCoursesForCurrentUser
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testListCoursesForCurrentUser()]
replaced return value with Collections.emptyList for edu/ucsb/cs156/frontiers/controllers/CoursesController::listCoursesForCurrentUser → KILLED

297

1.1
Location : lambda$listCoursesForCurrentUser$4
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testListCoursesForCurrentUser()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::lambda$listCoursesForCurrentUser$4 → KILLED

328

1.1
Location : staffCourses
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testStudenIsStaffInCourse()]
replaced return value with Collections.emptyList for edu/ucsb/cs156/frontiers/controllers/CoursesController::staffCourses → KILLED

342

1.1
Location : lambda$staffCourses$5
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testStudenIsStaffInCourse()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::lambda$staffCourses$5 → KILLED

357

1.1
Location : lambda$updateInstructorEmail$6
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testUpdateInstructorEmail_courseDoesNotExist()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::lambda$updateInstructorEmail$6 → KILLED

365

1.1
Location : updateInstructorEmail
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testUpdateInstructorEmail_emailNotFound()]
negated conditional → KILLED

2.2
Location : updateInstructorEmail
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testUpdateInstructorEmail_emailNotFound()]
negated conditional → KILLED

369

1.1
Location : updateInstructorEmail
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testUpdateInstructorEmail_byAdmin_email_is_admin()]
removed call to edu/ucsb/cs156/frontiers/entities/Course::setInstructorEmail → KILLED

372

1.1
Location : updateInstructorEmail
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:testUpdateInstructorEmail_byAdmin_email_is_instructor()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::updateInstructorEmail → KILLED

383

1.1
Location : lambda$deleteCourse$7
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:delete_not_found_returns_not_found()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::lambda$deleteCourse$7 → KILLED

386

1.1
Location : deleteCourse
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:delete_success_returns_ok()]
negated conditional → KILLED

2.2
Location : deleteCourse
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:delete_success_returns_ok()]
negated conditional → KILLED

390

1.1
Location : deleteCourse
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:delete_success_returns_ok()]
removed call to edu/ucsb/cs156/frontiers/services/OrganizationLinkerService::unenrollOrganization → KILLED

391

1.1
Location : deleteCourse
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:delete_success_returns_ok()]
removed call to edu/ucsb/cs156/frontiers/repositories/CourseRepository::delete → KILLED

392

1.1
Location : deleteCourse
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:delete_success_returns_ok()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::deleteCourse → KILLED

415

1.1
Location : lambda$updateCourse$8
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:update_course_not_found_returns_not_found()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::lambda$updateCourse$8 → KILLED

417

1.1
Location : updateCourse
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:admin_can_update_course_created_by_someone_else()]
removed call to edu/ucsb/cs156/frontiers/entities/Course::setCourseName → KILLED

418

1.1
Location : updateCourse
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:admin_can_update_course_created_by_someone_else()]
removed call to edu/ucsb/cs156/frontiers/entities/Course::setTerm → KILLED

419

1.1
Location : updateCourse
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:admin_can_update_course_created_by_someone_else()]
removed call to edu/ucsb/cs156/frontiers/entities/Course::setSchool → KILLED

423

1.1
Location : updateCourse
Killed by : edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.CoursesControllerTests]/[method:updateCourse_success_admin()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/CoursesController::updateCourse → KILLED

Active mutators

Tests examined


Report generated by PIT 1.17.0