WebhookController.java

1
package edu.ucsb.cs156.frontiers.controllers;
2
3
import com.fasterxml.jackson.core.JsonProcessingException;
4
import com.fasterxml.jackson.databind.JsonNode;
5
import edu.ucsb.cs156.frontiers.entities.Course;
6
import edu.ucsb.cs156.frontiers.entities.CourseStaff;
7
import edu.ucsb.cs156.frontiers.entities.RosterStudent;
8
import edu.ucsb.cs156.frontiers.enums.OrgStatus;
9
import edu.ucsb.cs156.frontiers.repositories.CourseRepository;
10
import edu.ucsb.cs156.frontiers.repositories.CourseStaffRepository;
11
import edu.ucsb.cs156.frontiers.repositories.RosterStudentRepository;
12
import edu.ucsb.cs156.frontiers.utilities.WebhookSecurityUtils;
13
import io.swagger.v3.oas.annotations.tags.Tag;
14
import java.security.InvalidKeyException;
15
import java.security.NoSuchAlgorithmException;
16
import java.util.Optional;
17
import lombok.extern.slf4j.Slf4j;
18
import org.springframework.beans.factory.annotation.Value;
19
import org.springframework.http.ResponseEntity;
20
import org.springframework.web.bind.annotation.PostMapping;
21
import org.springframework.web.bind.annotation.RequestBody;
22
import org.springframework.web.bind.annotation.RequestHeader;
23
import org.springframework.web.bind.annotation.RequestMapping;
24
import org.springframework.web.bind.annotation.RestController;
25
26
@Tag(name = "Webhooks Controller")
27
@RestController
28
@RequestMapping("/api/webhooks")
29
@Slf4j
30
public class WebhookController {
31
32
  private final CourseRepository courseRepository;
33
  private final RosterStudentRepository rosterStudentRepository;
34
  private final CourseStaffRepository courseStaffRepository;
35
36
  @Value("${app.webhook.secret}")
37
  private String webhookSecret;
38
39
  public WebhookController(
40
      CourseRepository courseRepository,
41
      RosterStudentRepository rosterStudentRepository,
42
      CourseStaffRepository courseStaffRepository) {
43
    this.courseRepository = courseRepository;
44
    this.rosterStudentRepository = rosterStudentRepository;
45
    this.courseStaffRepository = courseStaffRepository;
46
  }
47
48
  /**
49
   * Accepts webhooks from GitHub, currently to update the membership status of a RosterStudent.
50
   *
51
   * @param jsonBody body of the webhook. The description of the currently used webhook is available
52
   *     in docs/webhooks.md
53
   * @param signature the GitHub webhook signature header for security validation
54
   * @return either the word success so GitHub will not flag the webhook as a failure, or the
55
   *     updated RosterStudent
56
   */
57
  @PostMapping("/github")
58
  public ResponseEntity<String> createGitHubWebhook(
59
      @RequestBody String requestBody,
60
      @RequestHeader(value = "X-Hub-Signature-256", required = false) String signature)
61
      throws JsonProcessingException, NoSuchAlgorithmException, InvalidKeyException {
62
63
    // Validate webhook signature
64 1 1. createGitHubWebhook : negated conditional → KILLED
    if (!WebhookSecurityUtils.validateGitHubSignature(requestBody, signature, webhookSecret)) {
65
      log.error("Webhook signature validation failed");
66 1 1. createGitHubWebhook : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/WebhookController::createGitHubWebhook → KILLED
      return ResponseEntity.status(401).body("Unauthorized: Invalid signature");
67
    }
68
69
    // Parse JSON after signature validation
70
    JsonNode jsonBody;
71
    try {
72
      jsonBody = new com.fasterxml.jackson.databind.ObjectMapper().readTree(requestBody);
73
    } catch (JsonProcessingException e) {
74
      log.error("Failed to parse webhook JSON body", e);
75 1 1. createGitHubWebhook : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/WebhookController::createGitHubWebhook → KILLED
      return ResponseEntity.badRequest().body("Invalid JSON");
76
    }
77
78
    log.info("Received GitHub webhook: {}", jsonBody.toString());
79
80 1 1. createGitHubWebhook : negated conditional → KILLED
    if (!jsonBody.has("action")) {
81 1 1. createGitHubWebhook : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/WebhookController::createGitHubWebhook → KILLED
      return ResponseEntity.ok().body("success");
82
    }
83
84
    String action = jsonBody.get("action").asText();
85
    log.info("Webhook action: {}", action);
86
87
    // Handle GitHub App uninstall (installation deleted)
88 1 1. createGitHubWebhook : negated conditional → KILLED
    if (action.equals("deleted")) {
89 2 1. createGitHubWebhook : negated conditional → KILLED
2. createGitHubWebhook : negated conditional → KILLED
      if (!jsonBody.has("installation") || !jsonBody.get("installation").has("id")) {
90 1 1. createGitHubWebhook : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/WebhookController::createGitHubWebhook → KILLED
        return ResponseEntity.ok().body("success");
91
      }
92
      String installationIdForUninstall = jsonBody.get("installation").get("id").asText();
93
      log.info("Processing uninstall for Installation ID: {}", installationIdForUninstall);
94
      Optional<Course> courseForUninstall =
95
          courseRepository.findByInstallationId(installationIdForUninstall);
96
      log.info("Course found for uninstall: {}", courseForUninstall.isPresent());
97 1 1. createGitHubWebhook : negated conditional → KILLED
      if (courseForUninstall.isPresent()) {
98
        Course c = courseForUninstall.get();
99 1 1. createGitHubWebhook : removed call to edu/ucsb/cs156/frontiers/entities/Course::setInstallationId → KILLED
        c.setInstallationId(null);
100 1 1. createGitHubWebhook : removed call to edu/ucsb/cs156/frontiers/entities/Course::setOrgName → KILLED
        c.setOrgName(null);
101
        courseRepository.save(c);
102
      } else {
103
        log.warn(
104
            "No course found with installation ID for uninstall: {}", installationIdForUninstall);
105
      }
106 1 1. createGitHubWebhook : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/WebhookController::createGitHubWebhook → KILLED
      return ResponseEntity.ok().body("success");
107
    }
108
109
    // Early return if not an action we care about
110 2 1. createGitHubWebhook : negated conditional → KILLED
2. createGitHubWebhook : negated conditional → KILLED
    if (!action.equals("member_added") && !action.equals("member_invited")) {
111 1 1. createGitHubWebhook : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/WebhookController::createGitHubWebhook → KILLED
      return ResponseEntity.ok().body("success");
112
    }
113
114
    // Extract GitHub login based on payload structure
115
    String githubLogin = null;
116
    String installationId = null;
117
    OrgStatus role = null;
118
119
    // For member_added events, the structure is different
120 1 1. createGitHubWebhook : negated conditional → KILLED
    if (action.equals("member_added")) {
121 1 1. createGitHubWebhook : negated conditional → KILLED
      if (!jsonBody.has("membership")
122 1 1. createGitHubWebhook : negated conditional → KILLED
          || !jsonBody.get("membership").has("user")
123 1 1. createGitHubWebhook : negated conditional → KILLED
          || !jsonBody.get("membership").has("role")
124 1 1. createGitHubWebhook : negated conditional → KILLED
          || !jsonBody.get("membership").get("user").has("login")
125 1 1. createGitHubWebhook : negated conditional → KILLED
          || !jsonBody.has("installation")
126 1 1. createGitHubWebhook : negated conditional → KILLED
          || !jsonBody.get("installation").has("id")) {
127 1 1. createGitHubWebhook : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/WebhookController::createGitHubWebhook → KILLED
        return ResponseEntity.ok().body("success");
128
      }
129
130
      githubLogin = jsonBody.get("membership").get("user").get("login").asText();
131
      installationId = jsonBody.get("installation").get("id").asText();
132
      String textRole = jsonBody.get("membership").get("role").asText();
133 1 1. createGitHubWebhook : negated conditional → KILLED
      if (textRole.equals("admin")) {
134
        role = OrgStatus.OWNER;
135
      } else {
136
        role = OrgStatus.MEMBER;
137
      }
138
    }
139
    // For member_invited events, use the original structure
140
    else { // must be "member_invited" based on earlier check
141 1 1. createGitHubWebhook : negated conditional → KILLED
      if (!jsonBody.has("user")
142 1 1. createGitHubWebhook : negated conditional → KILLED
          || !jsonBody.get("user").has("login")
143 1 1. createGitHubWebhook : negated conditional → KILLED
          || !jsonBody.has("installation")
144 1 1. createGitHubWebhook : negated conditional → KILLED
          || !jsonBody.get("installation").has("id")) {
145 1 1. createGitHubWebhook : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/WebhookController::createGitHubWebhook → KILLED
        return ResponseEntity.ok().body("success");
146
      }
147
148
      githubLogin = jsonBody.get("user").get("login").asText();
149
      installationId = jsonBody.get("installation").get("id").asText();
150
    }
151
152
    log.info("GitHub login: {}, Installation ID: {}", githubLogin, installationId);
153
154
    Optional<Course> course = courseRepository.findByInstallationId(installationId);
155
    log.info("Course found: {}", course.isPresent());
156
157 1 1. createGitHubWebhook : negated conditional → KILLED
    if (!course.isPresent()) {
158
      log.warn("No course found with installation ID: {}", installationId);
159 1 1. createGitHubWebhook : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/WebhookController::createGitHubWebhook → KILLED
      return ResponseEntity.ok().body("success");
160
    }
161
162
    Optional<RosterStudent> student =
163
        rosterStudentRepository.findByCourseAndGithubLogin(course.get(), githubLogin);
164
    Optional<CourseStaff> staff =
165
        courseStaffRepository.findByCourseAndGithubLogin(course.get(), githubLogin);
166
    log.info("Student found: {}", student.isPresent());
167
    log.info("Staff found: {}", staff.isPresent());
168
169 2 1. createGitHubWebhook : negated conditional → KILLED
2. createGitHubWebhook : negated conditional → KILLED
    if (!student.isPresent() && !staff.isPresent()) {
170
      log.warn(
171
          "No student or staff found with GitHub login: {} in course: {}",
172
          githubLogin,
173
          course.get().getCourseName());
174 1 1. createGitHubWebhook : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/WebhookController::createGitHubWebhook → KILLED
      return ResponseEntity.ok().body("success");
175
    }
176
    StringBuilder response = new StringBuilder();
177 1 1. createGitHubWebhook : negated conditional → KILLED
    if (student.isPresent()) {
178
      RosterStudent updatedStudent = student.get();
179
      log.info("Current student org status: {}", updatedStudent.getOrgStatus());
180
181
      // Update status based on action
182 1 1. createGitHubWebhook : negated conditional → KILLED
      if (action.equals("member_added")) {
183 1 1. createGitHubWebhook : removed call to edu/ucsb/cs156/frontiers/entities/RosterStudent::setOrgStatus → KILLED
        updatedStudent.setOrgStatus(role);
184
        log.info("Setting status to {}", role.toString());
185
      } else { // must be "member_invited" based on earlier check
186 1 1. createGitHubWebhook : removed call to edu/ucsb/cs156/frontiers/entities/RosterStudent::setOrgStatus → KILLED
        updatedStudent.setOrgStatus(OrgStatus.INVITED);
187
        log.info("Setting status to INVITED");
188
      }
189
190
      rosterStudentRepository.save(updatedStudent);
191
      log.info("Student saved with new org status: {}", updatedStudent.getOrgStatus());
192
      response.append(updatedStudent);
193
    }
194 1 1. createGitHubWebhook : negated conditional → KILLED
    if (staff.isPresent()) {
195
      CourseStaff updatedStaff = staff.get();
196
      log.info("Current course staff member org status: {}", updatedStaff.getOrgStatus());
197
198
      // Update status based on action
199 1 1. createGitHubWebhook : negated conditional → KILLED
      if (action.equals("member_added")) {
200 1 1. createGitHubWebhook : removed call to edu/ucsb/cs156/frontiers/entities/CourseStaff::setOrgStatus → KILLED
        updatedStaff.setOrgStatus(role);
201
        log.info("Setting status to {}", role.toString());
202
      } else { // must be "member_invited" based on earlier check
203 1 1. createGitHubWebhook : removed call to edu/ucsb/cs156/frontiers/entities/CourseStaff::setOrgStatus → KILLED
        updatedStaff.setOrgStatus(OrgStatus.INVITED);
204
        log.info("Setting status to INVITED");
205
      }
206
207
      courseStaffRepository.save(updatedStaff);
208
      log.info("Course staff member saved with new org status: {}", updatedStaff.getOrgStatus());
209
      response.append(updatedStaff);
210
    }
211 1 1. createGitHubWebhook : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/WebhookController::createGitHubWebhook → KILLED
    return ResponseEntity.ok().body(response.toString());
212
  }
213
}

Mutations

64

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

66

1.1
Location : createGitHubWebhook
Killed by : edu.ucsb.cs156.frontiers.controllers.WebhookControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.WebhookControllerTests]/[method:unsuccessfulWebhook_noXHubSignature()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/WebhookController::createGitHubWebhook → KILLED

75

1.1
Location : createGitHubWebhook
Killed by : edu.ucsb.cs156.frontiers.controllers.WebhookControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.WebhookControllerTests]/[method:unsuccessfulWebhook_badJSON()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/WebhookController::createGitHubWebhook → KILLED

80

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

81

1.1
Location : createGitHubWebhook
Killed by : edu.ucsb.cs156.frontiers.controllers.WebhookControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.WebhookControllerTests]/[method:no_action()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/WebhookController::createGitHubWebhook → KILLED

88

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

89

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

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

90

1.1
Location : createGitHubWebhook
Killed by : edu.ucsb.cs156.frontiers.controllers.WebhookControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.WebhookControllerTests]/[method:uninstall_missingInstallationField_returns_success_noops()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/WebhookController::createGitHubWebhook → KILLED

97

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

99

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

100

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

106

1.1
Location : createGitHubWebhook
Killed by : edu.ucsb.cs156.frontiers.controllers.WebhookControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.WebhookControllerTests]/[method:uninstall_noCourseFound_returns_success()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/WebhookController::createGitHubWebhook → KILLED

110

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

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

111

1.1
Location : createGitHubWebhook
Killed by : edu.ucsb.cs156.frontiers.controllers.WebhookControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.WebhookControllerTests]/[method:testUnrecognizedAction_withValidFields()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/WebhookController::createGitHubWebhook → KILLED

120

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

121

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

122

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

123

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

124

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

125

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

126

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

127

1.1
Location : createGitHubWebhook
Killed by : edu.ucsb.cs156.frontiers.controllers.WebhookControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.WebhookControllerTests]/[method:memberAdded_missingUserField()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/WebhookController::createGitHubWebhook → KILLED

133

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

141

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

142

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

143

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

144

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

145

1.1
Location : createGitHubWebhook
Killed by : edu.ucsb.cs156.frontiers.controllers.WebhookControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.WebhookControllerTests]/[method:memberInvited_missingInstallationField()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/WebhookController::createGitHubWebhook → KILLED

157

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

159

1.1
Location : createGitHubWebhook
Killed by : edu.ucsb.cs156.frontiers.controllers.WebhookControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.WebhookControllerTests]/[method:noCourse()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/WebhookController::createGitHubWebhook → KILLED

169

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

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

174

1.1
Location : createGitHubWebhook
Killed by : edu.ucsb.cs156.frontiers.controllers.WebhookControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.WebhookControllerTests]/[method:noStudent()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/WebhookController::createGitHubWebhook → KILLED

177

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

182

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

183

1.1
Location : createGitHubWebhook
Killed by : edu.ucsb.cs156.frontiers.controllers.WebhookControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.WebhookControllerTests]/[method:successfulWebhook_admin()]
removed call to edu/ucsb/cs156/frontiers/entities/RosterStudent::setOrgStatus → KILLED

186

1.1
Location : createGitHubWebhook
Killed by : edu.ucsb.cs156.frontiers.controllers.WebhookControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.WebhookControllerTests]/[method:successfulWebhook_memberInvited()]
removed call to edu/ucsb/cs156/frontiers/entities/RosterStudent::setOrgStatus → KILLED

194

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

199

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

200

1.1
Location : createGitHubWebhook
Killed by : edu.ucsb.cs156.frontiers.controllers.WebhookControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.WebhookControllerTests]/[method:successfulWebhook_member_course_staff()]
removed call to edu/ucsb/cs156/frontiers/entities/CourseStaff::setOrgStatus → KILLED

203

1.1
Location : createGitHubWebhook
Killed by : edu.ucsb.cs156.frontiers.controllers.WebhookControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.WebhookControllerTests]/[method:courseStaffInvited()]
removed call to edu/ucsb/cs156/frontiers/entities/CourseStaff::setOrgStatus → KILLED

211

1.1
Location : createGitHubWebhook
Killed by : edu.ucsb.cs156.frontiers.controllers.WebhookControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.WebhookControllerTests]/[method:successfulWebhook_memberInvited()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/WebhookController::createGitHubWebhook → KILLED

Active mutators

Tests examined


Report generated by PIT 1.17.0