<commit_before>package unit;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import bio.terra.cli.serialization.userfacing.UFGroup;
import bio.terra.cli.serialization.userfacing.UFGroupMember;
import bio.terra.cli.service.SamService.GroupPolicy;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import harness.TestCommand;
import harness.TestUsers;
import harness.baseclasses.ClearContextUnit;
import harness.utils.SamGroups;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;

/** Tests for the `terra group` commands. */
@Tag("unit")
public class Group extends ClearContextUnit {
  SamGroups trackedGroups = new SamGroups();

  @AfterAll
  void cleanupOnce() throws IOException {
    // try to delete each group that was created by a method in this class
    trackedGroups.deleteAllTrackedGroups();
  }

  @Test
  @DisplayName("list, describe, list-users reflect creating and deleting a group")
  void listDescribeUsersReflectCreateDelete() throws IOException {
    TestUsers testUser = TestUsers.chooseTestUser();
    testUser.login();

    // `terra groups create --name=$name`
    String name = SamGroups.randomGroupName();
    UFGroup groupCreated =
        TestCommand.runAndParseCommandExpectSuccess(
            UFGroup.class, "groups", "create", "--name=" + name);

    // track the group so we can clean it up in case this test method fails
    trackedGroups.trackGroup(name, testUser);

    // check that the name and email match
    assertEquals(name, groupCreated.name, "group name matches after create");
    assertThat(
        "group email contains the name", groupCreated.email, CoreMatchers.containsString(name));
    assertThat(
        "group creator is an admin", groupCreated.currentUserPolicies.contains(GroupPolicy.ADMIN));

    // `terra groups list-users --name=$name`
    // check that the group creator is included in the list and is an admin
    expectListedMemberWithPolicies(name, testUser.email, GroupPolicy.ADMIN);

    // `terra groups list`
    List<UFGroup> groupList =
        TestCommand.runAndParseCommandExpectSuccess(new TypeReference<>() {}, "groups", "list");

    // check that the listed group matches the created one
    Optional<UFGroup> matchedGroup =
        groupList.stream().filter(listedGroup -> listedGroup.name.equals(name)).findAny();
    assertTrue(matchedGroup.isPresent(), "group appears in list after create");
    assertEquals(name, matchedGroup.get().name, "group name matches list output after create");
    assertEquals(
        groupCreated.email,
        matchedGroup.get().email,
        "group email matches list output after create");
    assertTrue(
        matchedGroup.get().currentUserPolicies.contains(GroupPolicy.ADMIN),
        "group policies for current user matches list output after create");

    // `terra groups describe --name=$name`
    UFGroup groupDescribed =
        TestCommand.runAndParseCommandExpectSuccess(
            UFGroup.class, "groups", "describe", "--name=" + name);

    // check that the described group matches the created one
    assertEquals(name, groupDescribed.name, "group name matches describe output after create");
    assertEquals(
        groupCreated.email,
        groupDescribed.email,
        "group email matches describe output after create");
    assertTrue(
        groupDescribed.currentUserPolicies.contains(GroupPolicy.ADMIN),
        "group policies for current user matches describe output after create");

    // `terra groups delete --name=$name`
    UFGroup groupDeleted =
        TestCommand.runAndParseCommandExpectSuccess(
            UFGroup.class, "groups", "delete", "--name=" + name);

    // check that the name and email match, and that the creator was an admin
    assertEquals(name, groupDeleted.name, "group name matches after delete");
    assertThat(
        "group email contained the name", groupDeleted.email, CoreMatchers.containsString(name));
    assertThat(
        "group creator was an admin", groupDeleted.currentUserPolicies.contains(GroupPolicy.ADMIN));

    // `terra groups list`
    groupList =
        TestCommand.runAndParseCommandExpectSuccess(new TypeReference<>() {}, "groups", "list");

    // check that the group is not included in the list output
    matchedGroup =
        groupList.stream().filter(listedGroup -> listedGroup.name.equals(name)).findAny();
    assertTrue(matchedGroup.isEmpty(), "group does not appear in list after delete");
  }

  @Test
  @DisplayName("describe, delete, list-users, add-user, remove-user all fail with invalid group")
  void invalidGroup() throws IOException {
    TestUsers.chooseTestUser().login();
    String badName = "terraCLI_nonexistentGroup";

    // `terra groups describe --name=$name`
    TestCommand.Result cmd = TestCommand.runCommand("groups", "describe", "--name=" + badName);
    expectGroupNotFound(cmd);

    // `terra groups delete --name=$name`
    cmd = TestCommand.runCommand("groups", "delete", "--name=" + badName);
    expectGroupNotFound(cmd);

    // `terra groups list-users --name=$name`
    cmd = TestCommand.runCommand("groups", "list-users", "--name=" + badName);
    expectGroupNotFound(cmd);

    // `terra groups add-user --name=$name`
    cmd =
        TestCommand.runCommand(
            "groups",
            "add-user",
            "--name=" + badName,
            "--email=" + TestUsers.chooseTestUser().email,
            "--policy=MEMBER");
    expectGroupNotFound(cmd);

    // `terra groups remove-user --name=$name`
    cmd =
        TestCommand.runCommand(
            "groups",
            "remove-user",
            "--name=" + badName,
            "--email=" + TestUsers.chooseTestUser().email,
            "--policy=MEMBER");
    expectGroupNotFound(cmd);
  }

  @Test
  @DisplayName("only an admin, not a member, can modify a group")
  void onlyAdminCanModifyGroup() throws IOException {
    TestUsers groupCreator = TestUsers.chooseTestUser();
    groupCreator.login();

    // `terra groups create --name=$name`
    String name = SamGroups.randomGroupName();
    TestCommand.runCommandExpectSuccess("groups", "create", "--name=" + name);

    // track the group so we can clean it up in case this test method fails
    trackedGroups.trackGroup(name, groupCreator);

    // `terra groups add-user --name=$name`
    TestUsers groupMember = TestUsers.chooseTestUserWhoIsNot(groupCreator);
    TestCommand.runCommandExpectSuccess(
        "groups", "add-user", "--name=" + name, "--email=" + groupMember.email, "--policy=MEMBER");

    // `terra groups delete --name=$name` as member
    groupMember.login();
    TestCommand.runCommandExpectExitCode(2, "groups", "delete", "--name=" + name);

    // `terra groups add-user --email=$email --policy=ADMIN` as member
    TestCommand.runCommandExpectExitCode(
        2,
        "groups",
        "add-user",
        "--name=" + name,
        "--email=" + groupMember.email,
        "--policy=ADMIN");

    // `terra groups remove-user --email=$email --policy=OWNER` as member
    TestCommand.runCommandExpectExitCode(
        2,
        "groups",
        "remove-user",
        "--name=" + name,
        "--email=" + groupMember.email,
        "--policy=MEMBER");

    // `terra groups delete --name=$name` as admin
    groupCreator.login();
    TestCommand.runCommandExpectSuccess("groups", "delete", "--name=" + name);
  }

  @Test
  @DisplayName("list-users reflects adding and removing a user")
  void listUsersReflectsAddRemove() throws IOException {
    TestUsers groupCreator = TestUsers.chooseTestUser();
    groupCreator.login();

    // `terra groups create --name=$name`
    String name = SamGroups.randomGroupName();
    TestCommand.runCommandExpectSuccess("groups", "create", "--name=" + name);
<commit_msg>Fix comment.<commit_after>package unit;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import bio.terra.cli.serialization.userfacing.UFGroup;
import bio.terra.cli.serialization.userfacing.UFGroupMember;
import bio.terra.cli.service.SamService.GroupPolicy;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import harness.TestCommand;
import harness.TestUsers;
import harness.baseclasses.ClearContextUnit;
import harness.utils.SamGroups;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;

/** Tests for the `terra group` commands. */
@Tag("unit")
public class Group extends ClearContextUnit {
  SamGroups trackedGroups = new SamGroups();

  @AfterAll
  void cleanupOnce() throws IOException {
    // try to delete each group that was created by a method in this class
    trackedGroups.deleteAllTrackedGroups();
  }

  @Test
  @DisplayName("list, describe, list-users reflect creating and deleting a group")
  void listDescribeUsersReflectCreateDelete() throws IOException {
    TestUsers testUser = TestUsers.chooseTestUser();
    testUser.login();

    // `terra groups create --name=$name`
    String name = SamGroups.randomGroupName();
    UFGroup groupCreated =
        TestCommand.runAndParseCommandExpectSuccess(
            UFGroup.class, "groups", "create", "--name=" + name);

    // track the group so we can clean it up in case this test method fails
    trackedGroups.trackGroup(name, testUser);

    // check that the name and email match
    assertEquals(name, groupCreated.name, "group name matches after create");
    assertThat(
        "group email contains the name", groupCreated.email, CoreMatchers.containsString(name));
    assertThat(
        "group creator is an admin", groupCreated.currentUserPolicies.contains(GroupPolicy.ADMIN));

    // `terra groups list-users --name=$name`
    // check that the group creator is included in the list and is an admin
    expectListedMemberWithPolicies(name, testUser.email, GroupPolicy.ADMIN);

    // `terra groups list`
    List<UFGroup> groupList =
        TestCommand.runAndParseCommandExpectSuccess(new TypeReference<>() {}, "groups", "list");

    // check that the listed group matches the created one
    Optional<UFGroup> matchedGroup =
        groupList.stream().filter(listedGroup -> listedGroup.name.equals(name)).findAny();
    assertTrue(matchedGroup.isPresent(), "group appears in list after create");
    assertEquals(name, matchedGroup.get().name, "group name matches list output after create");
    assertEquals(
        groupCreated.email,
        matchedGroup.get().email,
        "group email matches list output after create");
    assertTrue(
        matchedGroup.get().currentUserPolicies.contains(GroupPolicy.ADMIN),
        "group policies for current user matches list output after create");

    // `terra groups describe --name=$name`
    UFGroup groupDescribed =
        TestCommand.runAndParseCommandExpectSuccess(
            UFGroup.class, "groups", "describe", "--name=" + name);

    // check that the described group matches the created one
    assertEquals(name, groupDescribed.name, "group name matches describe output after create");
    assertEquals(
        groupCreated.email,
        groupDescribed.email,
        "group email matches describe output after create");
    assertTrue(
        groupDescribed.currentUserPolicies.contains(GroupPolicy.ADMIN),
        "group policies for current user matches describe output after create");

    // `terra groups delete --name=$name`
    UFGroup groupDeleted =
        TestCommand.runAndParseCommandExpectSuccess(
            UFGroup.class, "groups", "delete", "--name=" + name);

    // check that the name and email match, and that the creator was an admin
    assertEquals(name, groupDeleted.name, "group name matches after delete");
    assertThat(
        "group email contained the name", groupDeleted.email, CoreMatchers.containsString(name));
    assertThat(
        "group creator was an admin", groupDeleted.currentUserPolicies.contains(GroupPolicy.ADMIN));

    // `terra groups list`
    groupList =
        TestCommand.runAndParseCommandExpectSuccess(new TypeReference<>() {}, "groups", "list");

    // check that the group is not included in the list output
    matchedGroup =
        groupList.stream().filter(listedGroup -> listedGroup.name.equals(name)).findAny();
    assertTrue(matchedGroup.isEmpty(), "group does not appear in list after delete");
  }

  @Test
  @DisplayName("describe, delete, list-users, add-user, remove-user all fail with invalid group")
  void invalidGroup() throws IOException {
    TestUsers.chooseTestUser().login();
    String badName = "terraCLI_nonexistentGroup";

    // `terra groups describe --name=$name`
    TestCommand.Result cmd = TestCommand.runCommand("groups", "describe", "--name=" + badName);
    expectGroupNotFound(cmd);

    // `terra groups delete --name=$name`
    cmd = TestCommand.runCommand("groups", "delete", "--name=" + badName);
    expectGroupNotFound(cmd);

    // `terra groups list-users --name=$name`
    cmd = TestCommand.runCommand("groups", "list-users", "--name=" + badName);
    expectGroupNotFound(cmd);

    // `terra groups add-user --name=$name`
    cmd =
        TestCommand.runCommand(
            "groups",
            "add-user",
            "--name=" + badName,
            "--email=" + TestUsers.chooseTestUser().email,
            "--policy=MEMBER");
    expectGroupNotFound(cmd);

    // `terra groups remove-user --name=$name`
    cmd =
        TestCommand.runCommand(
            "groups",
            "remove-user",
            "--name=" + badName,
            "--email=" + TestUsers.chooseTestUser().email,
            "--policy=MEMBER");
    expectGroupNotFound(cmd);
  }

  @Test
  @DisplayName("only an admin, not a member, can modify a group")
  void onlyAdminCanModifyGroup() throws IOException {
    TestUsers groupCreator = TestUsers.chooseTestUser();
    groupCreator.login();

    // `terra groups create --name=$name`
    String name = SamGroups.randomGroupName();
    TestCommand.runCommandExpectSuccess("groups", "create", "--name=" + name);

    // track the group so we can clean it up in case this test method fails
    trackedGroups.trackGroup(name, groupCreator);

    // `terra groups add-user --name=$name`
    TestUsers groupMember = TestUsers.chooseTestUserWhoIsNot(groupCreator);
    TestCommand.runCommandExpectSuccess(
        "groups", "add-user", "--name=" + name, "--email=" + groupMember.email, "--policy=MEMBER");

    // `terra groups delete --name=$name` as member
    groupMember.login();
    TestCommand.runCommandExpectExitCode(2, "groups", "delete", "--name=" + name);

    // `terra groups add-user --email=$email --policy=ADMIN` as member
    TestCommand.runCommandExpectExitCode(
        2,
        "groups",
        "add-user",
        "--name=" + name,
        "--email=" + groupMember.email,
        "--policy=ADMIN");

    // `terra groups remove-user --email=$email --policy=MEMBER` as member
    TestCommand.runCommandExpectExitCode(
        2,
        "groups",
        "remove-user",
        "--name=" + name,
        "--email=" + groupMember.email,
        "--policy=MEMBER");

    // `terra groups delete --name=$name` as admin
    groupCreator.login();
    TestCommand.runCommandExpectSuccess("groups", "delete", "--name=" + name);
  }

  @Test
  @DisplayName("list-users reflects adding and removing a user")
  void listUsersReflectsAddRemove() throws IOException {
    TestUsers groupCreator = TestUsers.chooseTestUser();
    groupCreator.login();

    // `terra groups create --name=$name`
    String name = SamGroups.randomGroupName();
    TestCommand.runCommandExpectSuccess("groups", "create", "--name=" + name);

{'fraction_non_alphanumeric': 0.12200635386119257, 'fraction_numerical': 0.00036656891495601173, 'mean_word_length': 3.420469889278963, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4985807', 'n_tokens_mistral': 4467, 'n_tokens_neox': 4443, 'n_words': 1197}