GithubTeamService.java

1
package edu.ucsb.cs156.frontiers.services;
2
3
import com.fasterxml.jackson.core.JsonProcessingException;
4
import com.fasterxml.jackson.core.type.TypeReference;
5
import com.fasterxml.jackson.databind.DeserializationFeature;
6
import com.fasterxml.jackson.databind.JsonNode;
7
import com.fasterxml.jackson.databind.ObjectMapper;
8
import edu.ucsb.cs156.frontiers.entities.Course;
9
import edu.ucsb.cs156.frontiers.entities.Team;
10
import edu.ucsb.cs156.frontiers.enums.TeamStatus;
11
import java.security.NoSuchAlgorithmException;
12
import java.security.spec.InvalidKeySpecException;
13
import java.util.ArrayList;
14
import java.util.HashMap;
15
import java.util.List;
16
import java.util.Map;
17
import java.util.regex.Matcher;
18
import java.util.regex.Pattern;
19
import lombok.extern.slf4j.Slf4j;
20
import org.springframework.boot.web.client.RestTemplateBuilder;
21
import org.springframework.http.HttpEntity;
22
import org.springframework.http.HttpHeaders;
23
import org.springframework.http.HttpMethod;
24
import org.springframework.http.ResponseEntity;
25
import org.springframework.stereotype.Service;
26
import org.springframework.web.client.HttpClientErrorException;
27
import org.springframework.web.client.RestTemplate;
28
29
@Slf4j
30
@Service
31
public class GithubTeamService {
32
33
  public record GithubTeamInfo(Integer id, String name, String slug) {
34
    public GithubTeamInfo(Integer id, String name) {
35
      this(id, name, null);
36
    }
37
  }
38
39
  public record GithubTeamMemberInfo(String login) {}
40
41
  private final JwtService jwtService;
42
  private final ObjectMapper objectMapper;
43
  private final RestTemplate restTemplate;
44
45
  public GithubTeamService(
46
      JwtService jwtService, ObjectMapper objectMapper, RestTemplateBuilder builder) {
47
    this.jwtService = jwtService;
48
    this.objectMapper = objectMapper;
49
    this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
50
    this.restTemplate = builder.build();
51
  }
52
53
  /**
54
   * Creates a team on GitHub if it doesn't exist, or returns the existing team ID.
55
   *
56
   * @param team The team to create
57
   * @param course The course containing the organization
58
   * @return The GitHub team ID
59
   * @throws JsonProcessingException if there is an error processing JSON
60
   * @throws NoSuchAlgorithmException if there is an algorithm error
61
   * @throws InvalidKeySpecException if there is a key specification error
62
   */
63
  public Integer createOrGetTeamId(Team team, Course course)
64
      throws JsonProcessingException, NoSuchAlgorithmException, InvalidKeySpecException {
65
    GithubTeamInfo teamInfo = createOrGetTeamInfo(team, course);
66 2 1. createOrGetTeamId : negated conditional → KILLED
2. createOrGetTeamId : replaced Integer return value with 0 for edu/ucsb/cs156/frontiers/services/GithubTeamService::createOrGetTeamId → KILLED
    return teamInfo == null ? null : teamInfo.id();
67
  }
68
69
  /**
70
   * Creates a team on GitHub if it doesn't exist, or returns the existing team info.
71
   *
72
   * @param team The team to create
73
   * @param course The course containing the organization
74
   * @return The GitHub team info
75
   * @throws JsonProcessingException if there is an error processing JSON
76
   * @throws NoSuchAlgorithmException if there is an algorithm error
77
   * @throws InvalidKeySpecException if there is a key specification error
78
   */
79
  public GithubTeamInfo createOrGetTeamInfo(Team team, Course course)
80
      throws JsonProcessingException, NoSuchAlgorithmException, InvalidKeySpecException {
81
    GithubTeamInfo existingTeamInfo = null;
82 2 1. createOrGetTeamInfo : negated conditional → KILLED
2. createOrGetTeamInfo : negated conditional → KILLED
    if (team.getGithubTeamSlug() != null && !team.getGithubTeamSlug().isBlank()) {
83
      existingTeamInfo = getTeamInfo(team.getGithubTeamSlug(), course);
84
    }
85 1 1. createOrGetTeamInfo : negated conditional → KILLED
    if (existingTeamInfo == null) {
86
      existingTeamInfo = getTeamInfoByName(team.getName(), course);
87
    }
88 1 1. createOrGetTeamInfo : negated conditional → KILLED
    if (existingTeamInfo != null) {
89 1 1. createOrGetTeamInfo : replaced return value with null for edu/ucsb/cs156/frontiers/services/GithubTeamService::createOrGetTeamInfo → KILLED
      return existingTeamInfo;
90
    }
91
92
    // Create the team if it doesn't exist
93 1 1. createOrGetTeamInfo : replaced return value with null for edu/ucsb/cs156/frontiers/services/GithubTeamService::createOrGetTeamInfo → KILLED
    return createTeamInfo(team.getName(), course);
94
  }
95
96
  /**
97
   * Get the org id, given the org name.
98
   *
99
   * <p>Note: in the future, it would be better to cache this value in the Course row in the
100
   * database at the time the Github App is linked to the org, since it doesn't change.
101
   *
102
   * @param orgName
103
   * @param course
104
   * @return
105
   * @throws JsonProcessingException
106
   * @throws NoSuchAlgorithmException
107
   * @throws InvalidKeySpecException
108
   */
109
  public Integer getOrgId(String orgName, Course course)
110
      throws JsonProcessingException, NoSuchAlgorithmException, InvalidKeySpecException {
111
    String endpoint = "https://api.github.com/orgs/" + orgName;
112
    HttpHeaders headers = new HttpHeaders();
113
    String token = jwtService.getInstallationToken(course);
114 1 1. getOrgId : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("Authorization", "Bearer " + token);
115 1 1. getOrgId : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("Accept", "application/vnd.github+json");
116 1 1. getOrgId : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("X-GitHub-Api-Version", "2022-11-28");
117
    HttpEntity<String> entity = new HttpEntity<>(headers);
118
119
    ResponseEntity<String> response =
120
        restTemplate.exchange(endpoint, HttpMethod.GET, entity, String.class);
121
    JsonNode responseJson = objectMapper.readTree(response.getBody());
122 1 1. getOrgId : replaced Integer return value with 0 for edu/ucsb/cs156/frontiers/services/GithubTeamService::getOrgId → KILLED
    return responseJson.get("id").asInt();
123
  }
124
125
  /**
126
   * Gets the team ID for a team slug, returns null if team doesn't exist.
127
   *
128
   * @param teamSlug The slug of the team
129
   * @param course The course containing the organization
130
   * @return The GitHub team ID or null if not found
131
   * @throws JsonProcessingException if there is an error processing JSON
132
   * @throws NoSuchAlgorithmException if there is an algorithm error
133
   * @throws InvalidKeySpecException if there is a key specification error
134
   */
135
  public Integer getTeamId(String teamSlug, Course course)
136
      throws JsonProcessingException, NoSuchAlgorithmException, InvalidKeySpecException {
137
    GithubTeamInfo teamInfo = getTeamInfo(teamSlug, course);
138 2 1. getTeamId : replaced Integer return value with 0 for edu/ucsb/cs156/frontiers/services/GithubTeamService::getTeamId → KILLED
2. getTeamId : negated conditional → KILLED
    return teamInfo == null ? null : teamInfo.id();
139
  }
140
141
  /**
142
   * Gets the team info for a team slug, returns null if team doesn't exist.
143
   *
144
   * @param teamSlug The slug of the team
145
   * @param course The course containing the organization
146
   * @return The GitHub team info or null if not found
147
   * @throws JsonProcessingException if there is an error processing JSON
148
   * @throws NoSuchAlgorithmException if there is an algorithm error
149
   * @throws InvalidKeySpecException if there is a key specification error
150
   */
151
  public GithubTeamInfo getTeamInfo(String teamSlug, Course course)
152
      throws JsonProcessingException, NoSuchAlgorithmException, InvalidKeySpecException {
153
    String endpoint = "https://api.github.com/orgs/" + course.getOrgName() + "/teams/" + teamSlug;
154
    HttpHeaders headers = new HttpHeaders();
155
    String token = jwtService.getInstallationToken(course);
156 1 1. getTeamInfo : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("Authorization", "Bearer " + token);
157 1 1. getTeamInfo : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("Accept", "application/vnd.github+json");
158 1 1. getTeamInfo : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("X-GitHub-Api-Version", "2022-11-28");
159
    HttpEntity<String> entity = new HttpEntity<>(headers);
160
161
    try {
162
      ResponseEntity<String> response =
163
          restTemplate.exchange(endpoint, HttpMethod.GET, entity, String.class);
164 1 1. getTeamInfo : replaced return value with null for edu/ucsb/cs156/frontiers/services/GithubTeamService::getTeamInfo → KILLED
      return objectMapper.readValue(response.getBody(), GithubTeamInfo.class);
165
    } catch (HttpClientErrorException e) {
166 1 1. getTeamInfo : negated conditional → KILLED
      if (e.getStatusCode().value() == 404) {
167
        return null; // Team doesn't exist
168
      }
169
      throw e;
170
    }
171
  }
172
173
  /**
174
   * Gets the team info for a team ID, returns null if team doesn't exist.
175
   *
176
   * @param orgId The GitHub organization ID
177
   * @param teamId The GitHub team ID
178
   * @param course The course containing the organization
179
   * @return The GitHub team info or null if not found
180
   * @throws JsonProcessingException if there is an error processing JSON
181
   * @throws NoSuchAlgorithmException if there is an algorithm error
182
   * @throws InvalidKeySpecException if there is a key specification error
183
   */
184
  public GithubTeamInfo getTeamInfoById(Integer orgId, Integer teamId, Course course)
185
      throws JsonProcessingException, NoSuchAlgorithmException, InvalidKeySpecException {
186
    String endpoint = "https://api.github.com/organizations/" + orgId + "/team/" + teamId;
187
    HttpHeaders headers = new HttpHeaders();
188
    String token = jwtService.getInstallationToken(course);
189 1 1. getTeamInfoById : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("Authorization", "Bearer " + token);
190 1 1. getTeamInfoById : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("Accept", "application/vnd.github+json");
191 1 1. getTeamInfoById : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("X-GitHub-Api-Version", "2022-11-28");
192
    HttpEntity<String> entity = new HttpEntity<>(headers);
193
194
    try {
195
      ResponseEntity<String> response =
196
          restTemplate.exchange(endpoint, HttpMethod.GET, entity, String.class);
197 1 1. getTeamInfoById : replaced return value with null for edu/ucsb/cs156/frontiers/services/GithubTeamService::getTeamInfoById → KILLED
      return objectMapper.readValue(response.getBody(), GithubTeamInfo.class);
198
    } catch (HttpClientErrorException e) {
199 1 1. getTeamInfoById : negated conditional → KILLED
      if (e.getStatusCode().value() == 404) {
200
        return null;
201
      }
202
      throw e;
203
    }
204
  }
205
206
  /**
207
   * Finds team info by display name by searching the organization's teams.
208
   *
209
   * @param teamName The display name of the team
210
   * @param course The course containing the organization
211
   * @return The GitHub team info or null if not found
212
   * @throws JsonProcessingException if there is an error processing JSON
213
   * @throws NoSuchAlgorithmException if there is an algorithm error
214
   * @throws InvalidKeySpecException if there is a key specification error
215
   */
216
  public GithubTeamInfo getTeamInfoByName(String teamName, Course course)
217
      throws JsonProcessingException, NoSuchAlgorithmException, InvalidKeySpecException {
218
    for (GithubTeamInfo teamInfo : getAllTeams(course)) {
219 1 1. getTeamInfoByName : negated conditional → KILLED
      if (teamName.equals(teamInfo.name())) {
220 1 1. getTeamInfoByName : replaced return value with null for edu/ucsb/cs156/frontiers/services/GithubTeamService::getTeamInfoByName → KILLED
        return teamInfo;
221
      }
222
    }
223
    return null;
224
  }
225
226
  /**
227
   * Creates a new team on GitHub.
228
   *
229
   * @param teamName The name of the team to create
230
   * @param course The course containing the organization
231
   * @return The GitHub team ID
232
   * @throws JsonProcessingException if there is an error processing JSON
233
   * @throws NoSuchAlgorithmException if there is an algorithm error
234
   * @throws InvalidKeySpecException if there is a key specification error
235
   */
236
  public Integer createTeam(String teamName, Course course)
237
      throws JsonProcessingException, NoSuchAlgorithmException, InvalidKeySpecException {
238
    GithubTeamInfo teamInfo = createTeamInfo(teamName, course);
239 2 1. createTeam : replaced Integer return value with 0 for edu/ucsb/cs156/frontiers/services/GithubTeamService::createTeam → KILLED
2. createTeam : negated conditional → KILLED
    return teamInfo == null ? null : teamInfo.id();
240
  }
241
242
  /**
243
   * Creates a new team on GitHub.
244
   *
245
   * @param teamName The name of the team to create
246
   * @param course The course containing the organization
247
   * @return The GitHub team info
248
   * @throws JsonProcessingException if there is an error processing JSON
249
   * @throws NoSuchAlgorithmException if there is an algorithm error
250
   * @throws InvalidKeySpecException if there is a key specification error
251
   */
252
  public GithubTeamInfo createTeamInfo(String teamName, Course course)
253
      throws JsonProcessingException, NoSuchAlgorithmException, InvalidKeySpecException {
254
    String endpoint = "https://api.github.com/orgs/" + course.getOrgName() + "/teams";
255
    HttpHeaders headers = new HttpHeaders();
256
    String token = jwtService.getInstallationToken(course);
257 1 1. createTeamInfo : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("Authorization", "Bearer " + token);
258 1 1. createTeamInfo : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("Accept", "application/vnd.github+json");
259 1 1. createTeamInfo : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("X-GitHub-Api-Version", "2022-11-28");
260
261
    Map<String, Object> body = new HashMap<>();
262
    body.put("name", teamName);
263
    body.put("privacy", "closed"); // Teams are private by default
264
    String bodyAsJson = objectMapper.writeValueAsString(body);
265
    HttpEntity<String> entity = new HttpEntity<>(bodyAsJson, headers);
266
267
    ResponseEntity<String> response =
268
        restTemplate.exchange(endpoint, HttpMethod.POST, entity, String.class);
269
    GithubTeamInfo teamInfo = objectMapper.readValue(response.getBody(), GithubTeamInfo.class);
270
    log.info(
271
        "Created team '{}' with ID {} in organization {}",
272
        teamName,
273
        teamInfo.id(),
274
        course.getOrgName());
275 1 1. createTeamInfo : replaced return value with null for edu/ucsb/cs156/frontiers/services/GithubTeamService::createTeamInfo → KILLED
    return teamInfo;
276
  }
277
278
  /**
279
   * Deletes a team on GitHub.
280
   *
281
   * @param orgId The ID of the organization
282
   * @param githubTeamId The ID of the team to delete
283
   * @param course The course containing the organization
284
   * @throws JsonProcessingException if there is an error processing JSON
285
   * @throws NoSuchAlgorithmException if there is an algorithm error
286
   * @throws InvalidKeySpecException if there is a key specification error
287
   */
288
  public void deleteGithubTeam(Integer orgId, Integer teamId, Course course)
289
      throws JsonProcessingException, NoSuchAlgorithmException, InvalidKeySpecException {
290
    String endpoint = "https://api.github.com/organizations/" + orgId + "/team/" + teamId;
291
    HttpHeaders headers = new HttpHeaders();
292
    String token = jwtService.getInstallationToken(course);
293 1 1. deleteGithubTeam : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("Authorization", "Bearer " + token);
294 1 1. deleteGithubTeam : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("Accept", "application/vnd.github+json");
295 1 1. deleteGithubTeam : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("X-GitHub-Api-Version", "2022-11-28");
296
    HttpEntity<String> entity = new HttpEntity<>(headers);
297
298
    restTemplate.exchange(endpoint, HttpMethod.DELETE, entity, String.class);
299
    log.info("Deleted team with ID {} in organization {}", teamId, course.getOrgName());
300
  }
301
302
  /**
303
   * Gets the current team membership status for a user.
304
   *
305
   * @param githubLogin The GitHub login of the user
306
   * @param teamId The GitHub team ID
307
   * @param course The course containing the organization
308
   * @param orgId The GitHub organization ID
309
   * @return The team status of the user
310
   * @throws JsonProcessingException if there is an error processing JSON
311
   * @throws NoSuchAlgorithmException if there is an algorithm error
312
   * @throws InvalidKeySpecException if there is a key specification error
313
   */
314
  public TeamStatus getTeamMembershipStatus(
315
      String githubLogin, Integer teamId, Course course, Integer orgId)
316
      throws JsonProcessingException, NoSuchAlgorithmException, InvalidKeySpecException {
317 1 1. getTeamMembershipStatus : negated conditional → KILLED
    if (githubLogin == null) {
318 1 1. getTeamMembershipStatus : replaced return value with null for edu/ucsb/cs156/frontiers/services/GithubTeamService::getTeamMembershipStatus → KILLED
      return TeamStatus.NO_GITHUB_ID;
319
    }
320
321
    String endpoint =
322
        "https://api.github.com/organizations/"
323
            + orgId
324
            + "/team/"
325
            + teamId
326
            + "/memberships/"
327
            + githubLogin;
328
    HttpHeaders headers = new HttpHeaders();
329
    String token = jwtService.getInstallationToken(course);
330 1 1. getTeamMembershipStatus : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("Authorization", "Bearer " + token);
331 1 1. getTeamMembershipStatus : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("Accept", "application/vnd.github+json");
332 1 1. getTeamMembershipStatus : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("X-GitHub-Api-Version", "2022-11-28");
333
    HttpEntity<String> entity = new HttpEntity<>(headers);
334
335
    try {
336
      ResponseEntity<String> response =
337
          restTemplate.exchange(endpoint, HttpMethod.GET, entity, String.class);
338
      JsonNode responseJson = objectMapper.readTree(response.getBody());
339
      String role = responseJson.get("role").asText();
340 2 1. getTeamMembershipStatus : negated conditional → KILLED
2. getTeamMembershipStatus : replaced return value with null for edu/ucsb/cs156/frontiers/services/GithubTeamService::getTeamMembershipStatus → KILLED
      return "maintainer".equalsIgnoreCase(role)
341
          ? TeamStatus.TEAM_MAINTAINER
342
          : TeamStatus.TEAM_MEMBER;
343
    } catch (HttpClientErrorException e) {
344 1 1. getTeamMembershipStatus : negated conditional → KILLED
      if (e.getStatusCode().value() == 404) {
345 1 1. getTeamMembershipStatus : replaced return value with null for edu/ucsb/cs156/frontiers/services/GithubTeamService::getTeamMembershipStatus → KILLED
        return TeamStatus.NOT_ORG_MEMBER; // User is not a member of the team
346
      }
347
      throw e;
348
    }
349
  }
350
351
  /**
352
   * Adds a member to a GitHub team.
353
   *
354
   * @param githubLogin The GitHub login of the user to add
355
   * @param teamId The GitHub team ID
356
   * @param role The role to assign ("member" or "maintainer")
357
   * @param course The course containing the organization
358
   * @return The resulting team status
359
   * @throws JsonProcessingException if there is an error processing JSON
360
   * @throws NoSuchAlgorithmException if there is an algorithm error
361
   * @throws InvalidKeySpecException if there is a key specification error
362
   */
363
  public TeamStatus addMemberToGithubTeam(
364
      String githubLogin, Integer teamId, String role, Course course, Integer orgId)
365
      throws JsonProcessingException, NoSuchAlgorithmException, InvalidKeySpecException {
366
    String endpoint =
367
        "https://api.github.com/organizations/"
368
            + orgId
369
            + "/team/"
370
            + teamId
371
            + "/memberships/"
372
            + githubLogin;
373
    HttpHeaders headers = new HttpHeaders();
374
    String token = jwtService.getInstallationToken(course);
375 1 1. addMemberToGithubTeam : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("Authorization", "Bearer " + token);
376 1 1. addMemberToGithubTeam : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("Accept", "application/vnd.github+json");
377 1 1. addMemberToGithubTeam : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("X-GitHub-Api-Version", "2022-11-28");
378
379
    Map<String, Object> body = new HashMap<>();
380
    body.put("role", role);
381
    String bodyAsJson = objectMapper.writeValueAsString(body);
382
    HttpEntity<String> entity = new HttpEntity<>(bodyAsJson, headers);
383
384
    ResponseEntity<String> response =
385
        restTemplate.exchange(endpoint, HttpMethod.PUT, entity, String.class);
386
    JsonNode responseJson = objectMapper.readTree(response.getBody());
387
    String resultRole = responseJson.get("role").asText();
388
    log.info("Added user '{}' to team ID {} with role '{}'", githubLogin, teamId, resultRole);
389 2 1. addMemberToGithubTeam : negated conditional → KILLED
2. addMemberToGithubTeam : replaced return value with null for edu/ucsb/cs156/frontiers/services/GithubTeamService::addMemberToGithubTeam → KILLED
    return "maintainer".equalsIgnoreCase(resultRole)
390
        ? TeamStatus.TEAM_MAINTAINER
391
        : TeamStatus.TEAM_MEMBER;
392
  }
393
394
  /**
395
   * Removes a member from a GitHub team
396
   *
397
   * @param orgId
398
   * @param githubLogin
399
   * @param teamId
400
   * @param course
401
   * @throws NoSuchAlgorithmException
402
   * @throws InvalidKeySpecException
403
   * @throws JsonProcessingException
404
   */
405
  public void removeMemberFromGithubTeam(
406
      Integer orgId, String githubLogin, Integer teamId, Course course)
407
      throws NoSuchAlgorithmException, InvalidKeySpecException, JsonProcessingException {
408
409
    String endpoint =
410
        "https://api.github.com/organizations/"
411
            + orgId
412
            + "/team/"
413
            + teamId
414
            + "/memberships/"
415
            + githubLogin;
416
    HttpHeaders headers = new HttpHeaders();
417
    String token = jwtService.getInstallationToken(course);
418 1 1. removeMemberFromGithubTeam : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("Authorization", "Bearer " + token);
419 1 1. removeMemberFromGithubTeam : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("Accept", "application/vnd.github+json");
420 1 1. removeMemberFromGithubTeam : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("X-GitHub-Api-Version", "2022-11-28");
421
    HttpEntity<String> entity = new HttpEntity<>(headers);
422
423
    restTemplate.exchange(endpoint, HttpMethod.DELETE, entity, String.class);
424
    log.info("Successfully removed member {} from team ID {}", githubLogin, teamId);
425
  }
426
427
  /**
428
   * Returns all team members for a GitHub team.
429
   *
430
   * @param teamSlug The GitHub team slug
431
   * @param course The course containing the organization
432
   * @return A map of github login to TeamStatus
433
   * @throws NoSuchAlgorithmException if there is an algorithm error
434
   * @throws InvalidKeySpecException if there is a key specification error
435
   * @throws JsonProcessingException if there is an error processing JSON
436
   */
437
  public Map<String, TeamStatus> getTeamMemberships(String teamSlug, Course course)
438
      throws NoSuchAlgorithmException, InvalidKeySpecException, JsonProcessingException {
439 2 1. getTeamMemberships : negated conditional → KILLED
2. getTeamMemberships : negated conditional → KILLED
    if (teamSlug == null || teamSlug.isBlank()) {
440
      throw new IllegalArgumentException("teamSlug must be provided");
441
    }
442
    HttpHeaders headers = new HttpHeaders();
443
    String token = jwtService.getInstallationToken(course);
444 1 1. getTeamMemberships : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("Authorization", "Bearer " + token);
445 1 1. getTeamMemberships : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("Accept", "application/vnd.github+json");
446 1 1. getTeamMemberships : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("X-GitHub-Api-Version", "2022-11-28");
447
    HttpEntity<String> entity = new HttpEntity<>(headers);
448
449
    Map<String, TeamStatus> memberships = new HashMap<>();
450
    String endpointPrefix =
451
        "https://api.github.com/orgs/" + course.getOrgName() + "/teams/" + teamSlug + "/members";
452 1 1. getTeamMemberships : removed call to edu/ucsb/cs156/frontiers/services/GithubTeamService::addMembershipsByRole → KILLED
    addMembershipsByRole(endpointPrefix, "member", TeamStatus.TEAM_MEMBER, entity, memberships);
453 1 1. getTeamMemberships : removed call to edu/ucsb/cs156/frontiers/services/GithubTeamService::addMembershipsByRole → KILLED
    addMembershipsByRole(
454
        endpointPrefix, "maintainer", TeamStatus.TEAM_MAINTAINER, entity, memberships);
455
456 1 1. getTeamMemberships : replaced return value with Collections.emptyMap for edu/ucsb/cs156/frontiers/services/GithubTeamService::getTeamMemberships → KILLED
    return memberships;
457
  }
458
459
  private void addMembershipsByRole(
460
      String endpointPrefix,
461
      String role,
462
      TeamStatus status,
463
      HttpEntity<String> entity,
464
      Map<String, TeamStatus> memberships)
465
      throws JsonProcessingException {
466
    String endpoint = endpointPrefix + "?per_page=100&role=" + role;
467
    Pattern pattern = Pattern.compile("(?<=<)([\\S]*)(?=>; rel=\"next\")");
468
469
    ResponseEntity<String> response =
470
        restTemplate.exchange(endpoint, HttpMethod.GET, entity, String.class);
471
    List<String> responseLinks = response.getHeaders().getOrEmpty("link");
472
473 2 1. addMembershipsByRole : negated conditional → KILLED
2. addMembershipsByRole : negated conditional → KILLED
    while (!responseLinks.isEmpty() && responseLinks.getFirst().contains("next")) {
474
      for (GithubTeamMemberInfo member :
475
          objectMapper.convertValue(
476
              objectMapper.readTree(response.getBody()),
477
              new TypeReference<List<GithubTeamMemberInfo>>() {})) {
478
        memberships.put(member.login(), status);
479
      }
480
481
      Matcher matcher = pattern.matcher(responseLinks.getFirst());
482
      matcher.find();
483
      response = restTemplate.exchange(matcher.group(0), HttpMethod.GET, entity, String.class);
484
      responseLinks = response.getHeaders().getOrEmpty("link");
485
    }
486
487
    for (GithubTeamMemberInfo member :
488
        objectMapper.convertValue(
489
            objectMapper.readTree(response.getBody()),
490
            new TypeReference<List<GithubTeamMemberInfo>>() {})) {
491
      memberships.put(member.login(), status);
492
    }
493
  }
494
495
  /**
496
   * Returns all teams for an organization, following pagination links when present.
497
   *
498
   * @param course The course containing the organization
499
   * @return A list of GitHub teams with id and name
500
   * @throws NoSuchAlgorithmException if there is an algorithm error
501
   * @throws InvalidKeySpecException if there is a key specification error
502
   * @throws JsonProcessingException if there is an error processing JSON
503
   */
504
  public List<GithubTeamInfo> getAllTeams(Course course)
505
      throws NoSuchAlgorithmException, InvalidKeySpecException, JsonProcessingException {
506
    String endpoint = "https://api.github.com/orgs/" + course.getOrgName() + "/teams?per_page=100";
507
    Pattern pattern = Pattern.compile("(?<=<)([\\S]*)(?=>; rel=\"next\")");
508
509
    HttpHeaders headers = new HttpHeaders();
510
    String token = jwtService.getInstallationToken(course);
511 1 1. getAllTeams : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("Authorization", "Bearer " + token);
512 1 1. getAllTeams : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("Accept", "application/vnd.github+json");
513 1 1. getAllTeams : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("X-GitHub-Api-Version", "2022-11-28");
514
    HttpEntity<String> entity = new HttpEntity<>(headers);
515
516
    ResponseEntity<String> response =
517
        restTemplate.exchange(endpoint, HttpMethod.GET, entity, String.class);
518
    List<String> responseLinks = response.getHeaders().getOrEmpty("link");
519
    List<GithubTeamInfo> teams = new ArrayList<>();
520
521 2 1. getAllTeams : negated conditional → KILLED
2. getAllTeams : negated conditional → KILLED
    while (!responseLinks.isEmpty() && responseLinks.getFirst().contains("next")) {
522
      teams.addAll(
523
          objectMapper.convertValue(
524
              objectMapper.readTree(response.getBody()),
525
              new TypeReference<List<GithubTeamInfo>>() {}));
526
527
      Matcher matcher = pattern.matcher(responseLinks.getFirst());
528
      matcher.find();
529
      response = restTemplate.exchange(matcher.group(0), HttpMethod.GET, entity, String.class);
530
      responseLinks = response.getHeaders().getOrEmpty("link");
531
    }
532
533
    teams.addAll(
534
        objectMapper.convertValue(
535
            objectMapper.readTree(response.getBody()),
536
            new TypeReference<List<GithubTeamInfo>>() {}));
537
538 1 1. getAllTeams : replaced return value with Collections.emptyList for edu/ucsb/cs156/frontiers/services/GithubTeamService::getAllTeams → KILLED
    return teams;
539
  }
540
}

Mutations

66

1.1
Location : createOrGetTeamId
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testCreateOrGetTeamId_ReturnsNullWhenCreateOrGetTeamInfoReturnsNull()]
negated conditional → KILLED

2.2
Location : createOrGetTeamId
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testCreateOrGetTeamId_ReturnsNullWhenCreateOrGetTeamInfoReturnsNull()]
replaced Integer return value with 0 for edu/ucsb/cs156/frontiers/services/GithubTeamService::createOrGetTeamId → KILLED

82

1.1
Location : createOrGetTeamInfo
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testCreateOrGetTeamInfo_WhenTeamExists()]
negated conditional → KILLED

2.2
Location : createOrGetTeamInfo
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testCreateOrGetTeamInfo_WhenTeamExists()]
negated conditional → KILLED

85

1.1
Location : createOrGetTeamInfo
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testCreateOrGetTeamInfo_WhenTeamExists()]
negated conditional → KILLED

88

1.1
Location : createOrGetTeamInfo
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testCreateOrGetTeamInfo_WhenTeamExists()]
negated conditional → KILLED

89

1.1
Location : createOrGetTeamInfo
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testCreateOrGetTeamInfo_WhenTeamExists()]
replaced return value with null for edu/ucsb/cs156/frontiers/services/GithubTeamService::createOrGetTeamInfo → KILLED

93

1.1
Location : createOrGetTeamInfo
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testCreateOrGetTeamId_WhenTeamDoesNotExist()]
replaced return value with null for edu/ucsb/cs156/frontiers/services/GithubTeamService::createOrGetTeamInfo → KILLED

114

1.1
Location : getOrgId
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetOrgId_VerifyHeaders()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

115

1.1
Location : getOrgId
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetOrgId_VerifyHeaders()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

116

1.1
Location : getOrgId
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetOrgId_VerifyHeaders()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

122

1.1
Location : getOrgId
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:test_getOrgId_whenOrgExists()]
replaced Integer return value with 0 for edu/ucsb/cs156/frontiers/services/GithubTeamService::getOrgId → KILLED

138

1.1
Location : getTeamId
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamId_WhenTeamExists()]
replaced Integer return value with 0 for edu/ucsb/cs156/frontiers/services/GithubTeamService::getTeamId → KILLED

2.2
Location : getTeamId
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamId_WhenTeamExists()]
negated conditional → KILLED

156

1.1
Location : getTeamInfo
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamId_VerifyHeaders()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

157

1.1
Location : getTeamInfo
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamId_VerifyHeaders()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

158

1.1
Location : getTeamInfo
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamId_VerifyHeaders()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

164

1.1
Location : getTeamInfo
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamId_WhenTeamExists()]
replaced return value with null for edu/ucsb/cs156/frontiers/services/GithubTeamService::getTeamInfo → KILLED

166

1.1
Location : getTeamInfo
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamId_WhenTeamDoesNotExist()]
negated conditional → KILLED

189

1.1
Location : getTeamInfoById
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamInfoById_VerifyHeaders()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

190

1.1
Location : getTeamInfoById
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamInfoById_VerifyHeaders()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

191

1.1
Location : getTeamInfoById
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamInfoById_VerifyHeaders()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

197

1.1
Location : getTeamInfoById
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamInfoById_WhenTeamExists()]
replaced return value with null for edu/ucsb/cs156/frontiers/services/GithubTeamService::getTeamInfoById → KILLED

199

1.1
Location : getTeamInfoById
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamInfoById_WhenTeamDoesNotExist()]
negated conditional → KILLED

219

1.1
Location : getTeamInfoByName
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamInfoByName_WhenNoMatchReturnsNull()]
negated conditional → KILLED

220

1.1
Location : getTeamInfoByName
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testCreateOrGetTeamInfo_FallsBackToLookupByNameWhenSlugMissing()]
replaced return value with null for edu/ucsb/cs156/frontiers/services/GithubTeamService::getTeamInfoByName → KILLED

239

1.1
Location : createTeam
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testCreateTeam_ReturnsNullWhenCreateTeamInfoReturnsNull()]
replaced Integer return value with 0 for edu/ucsb/cs156/frontiers/services/GithubTeamService::createTeam → KILLED

2.2
Location : createTeam
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testCreateTeam_ReturnsNullWhenCreateTeamInfoReturnsNull()]
negated conditional → KILLED

257

1.1
Location : createTeamInfo
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testCreateTeam_VerifyHeaders()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

258

1.1
Location : createTeamInfo
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testCreateTeam_VerifyHeaders()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

259

1.1
Location : createTeamInfo
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testCreateTeam_VerifyHeaders()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

275

1.1
Location : createTeamInfo
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testCreateTeam_ReturnsIdWhenTeamDoesNotExist()]
replaced return value with null for edu/ucsb/cs156/frontiers/services/GithubTeamService::createTeamInfo → KILLED

293

1.1
Location : deleteGithubTeam
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testRemoveTeam_VerifyHeaders()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

294

1.1
Location : deleteGithubTeam
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testRemoveTeam_VerifyHeaders()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

295

1.1
Location : deleteGithubTeam
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testRemoveTeam_VerifyHeaders()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

317

1.1
Location : getTeamMembershipStatus
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamMembershipStatus_NoGithubId()]
negated conditional → KILLED

318

1.1
Location : getTeamMembershipStatus
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamMembershipStatus_NoGithubId()]
replaced return value with null for edu/ucsb/cs156/frontiers/services/GithubTeamService::getTeamMembershipStatus → KILLED

330

1.1
Location : getTeamMembershipStatus
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamMembershipStatus_VerifyHeaders()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

331

1.1
Location : getTeamMembershipStatus
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamMembershipStatus_VerifyHeaders()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

332

1.1
Location : getTeamMembershipStatus
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamMembershipStatus_VerifyHeaders()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

340

1.1
Location : getTeamMembershipStatus
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamMembershipStatus_TeamMember()]
negated conditional → KILLED

2.2
Location : getTeamMembershipStatus
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamMembershipStatus_TeamMember()]
replaced return value with null for edu/ucsb/cs156/frontiers/services/GithubTeamService::getTeamMembershipStatus → KILLED

344

1.1
Location : getTeamMembershipStatus
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamMembershipStatus_NotOrgMember()]
negated conditional → KILLED

345

1.1
Location : getTeamMembershipStatus
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamMembershipStatus_NotOrgMember()]
replaced return value with null for edu/ucsb/cs156/frontiers/services/GithubTeamService::getTeamMembershipStatus → KILLED

375

1.1
Location : addMemberToGithubTeam
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testAddTeamMember_VerifyHeaders()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

376

1.1
Location : addMemberToGithubTeam
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testAddTeamMember_VerifyHeaders()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

377

1.1
Location : addMemberToGithubTeam
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testAddTeamMember_VerifyHeaders()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

389

1.1
Location : addMemberToGithubTeam
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testAddTeamMember_AsMember()]
negated conditional → KILLED

2.2
Location : addMemberToGithubTeam
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testAddTeamMember_AsMember()]
replaced return value with null for edu/ucsb/cs156/frontiers/services/GithubTeamService::addMemberToGithubTeam → KILLED

418

1.1
Location : removeMemberFromGithubTeam
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testRemoveTeamMember_VerifyHeaders()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

419

1.1
Location : removeMemberFromGithubTeam
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testRemoveTeamMember_VerifyHeaders()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

420

1.1
Location : removeMemberFromGithubTeam
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testRemoveTeamMember_VerifyHeaders()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

439

1.1
Location : getTeamMemberships
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamMemberships_ThrowsExceptionWhenTeamSlugIsNull()]
negated conditional → KILLED

2.2
Location : getTeamMemberships
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamMemberships_ThrowsExceptionWhenTeamSlugIsBlank()]
negated conditional → KILLED

444

1.1
Location : getTeamMemberships
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamMemberships_VerifyHeaders()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

445

1.1
Location : getTeamMemberships
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamMemberships_VerifyHeaders()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

446

1.1
Location : getTeamMemberships
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamMemberships_VerifyHeaders()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

452

1.1
Location : getTeamMemberships
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamMemberships_MemberAndMaintainer()]
removed call to edu/ucsb/cs156/frontiers/services/GithubTeamService::addMembershipsByRole → KILLED

453

1.1
Location : getTeamMemberships
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamMemberships_MemberAndMaintainer()]
removed call to edu/ucsb/cs156/frontiers/services/GithubTeamService::addMembershipsByRole → KILLED

456

1.1
Location : getTeamMemberships
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamMemberships_MemberAndMaintainer()]
replaced return value with Collections.emptyMap for edu/ucsb/cs156/frontiers/services/GithubTeamService::getTeamMemberships → KILLED

473

1.1
Location : addMembershipsByRole
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamMemberships_MemberAndMaintainer()]
negated conditional → KILLED

2.2
Location : addMembershipsByRole
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetTeamMemberships_WithPagination()]
negated conditional → KILLED

511

1.1
Location : getAllTeams
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetAllTeams_VerifyHeaders()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

512

1.1
Location : getAllTeams
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetAllTeams_VerifyHeaders()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

513

1.1
Location : getAllTeams
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetAllTeams_VerifyHeaders()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

521

1.1
Location : getAllTeams
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetAllTeams_SinglePage()]
negated conditional → KILLED

2.2
Location : getAllTeams
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetAllTeams_WithPagination()]
negated conditional → KILLED

538

1.1
Location : getAllTeams
Killed by : edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.services.GithubTeamServiceTests]/[method:testGetAllTeams_SinglePage()]
replaced return value with Collections.emptyList for edu/ucsb/cs156/frontiers/services/GithubTeamService::getAllTeams → KILLED

Active mutators

Tests examined


Report generated by PIT 1.17.0