Esempio n. 1
0
class TestTeamCommand(TestCase):
    """Test case for TeamCommand class."""

    def setUp(self):
        """Set up the test case environment."""
        self.app = Flask(__name__)
        self.gh = mock.MagicMock()
        self.db = mock.MagicMock()
        self.sc = mock.MagicMock()
        self.testcommand = TeamCommand(self.db, self.gh, self.sc)
        self.help_text = self.testcommand.help
        self.maxDiff = None

    def test_get_name(self):
        """Test team command get_name method."""
        self.assertEqual(self.testcommand.get_name(), "team")

    def test_get_help(self):
        """Test team command get_help method."""
        subcommands = list(self.testcommand.subparser.choices.keys())
        help_message = self.testcommand.get_help()
        self.assertEqual(len(subcommands), help_message.count("usage"))

    def test_get_subcommand_help(self):
        """Test team command get_help method for specific subcommands."""
        subcommands = list(self.testcommand.subparser.choices.keys())
        for subcommand in subcommands:
            help_message = self.testcommand.get_help(subcommand=subcommand)
            self.assertEqual(1, help_message.count("usage"))

    def test_get_invalid_subcommand_help(self):
        """Test team command get_help method for invalid subcommands."""
        self.assertEqual(self.testcommand.get_help(),
                         self.testcommand.get_help(subcommand="foo"))

    def test_handle_help(self):
        """Test team command help parser."""
        ret, code = self.testcommand.handle("team help", user)
        self.assertEqual(ret, self.testcommand.get_help())
        self.assertEqual(code, 200)

    def test_handle_multiple_subcommands(self):
        """Test handling multiple observed subcommands."""
        ret, code = self.testcommand.handle("team list edit", user)
        self.assertEqual(ret, self.testcommand.get_help())
        self.assertEqual(code, 200)

    def test_handle_subcommand_help(self):
        """Test team subcommand help text."""
        subcommands = list(self.testcommand.subparser.choices.keys())
        for subcommand in subcommands:
            command = f"team {subcommand} --help"
            ret, code = self.testcommand.handle(command, user)
            self.assertEqual(1, ret.count("usage"))
            self.assertEqual(code, 200)

            command = f"team {subcommand} -h"
            ret, code = self.testcommand.handle(command, user)
            self.assertEqual(1, ret.count("usage"))
            self.assertEqual(code, 200)

            command = f"team {subcommand} --invalid argument"
            ret, code = self.testcommand.handle(command, user)
            self.assertEqual(1, ret.count("usage"))
            self.assertEqual(code, 200)

    def test_handle_list(self):
        """Test team command list parser."""
        team = Team("BRS", "brs", "web")
        team2 = Team("OTEAM", "other team", "android")
        self.db.query.return_value = [team, team2]
        attach = team.get_basic_attachment()
        attach2 = team2.get_basic_attachment()
        attachment = [attach, attach2]
        with self.app.app_context():
            resp, code = self.testcommand.handle("team list", user)
            expect = {'attachments': attachment}
            self.assertDictEqual(resp, expect)
            self.assertEqual(code, 200)
        self.db.query.assert_called_once_with(Team)

    def test_handle_list_no_teams(self):
        """Test team command list with no teams found."""
        self.db.query.return_value = []
        self.assertTupleEqual(self.testcommand.handle("team list", user),
                              ("No Teams Exist!", 200))

    def test_handle_view(self):
        """Test team command view parser."""
        team = Team("BRS", "brs", "web")
        team_attach = [team.get_attachment()]
        self.db.query.return_value = [team]
        with self.app.app_context():
            resp, code = self.testcommand.handle("team view brs", user)
            expect = {'attachments': team_attach}
            self.assertDictEqual(resp, expect)
            self.assertEqual(code, 200)

    def test_handle_view_lookup_error(self):
        """Test team command view parser with lookup error."""
        self.db.query.return_value = []
        self.assertTupleEqual(self.testcommand.handle("team view brs", user),
                              (self.testcommand.lookup_error, 200))

    def test_handle_delete_not_admin(self):
        """Test team command delete parser with improper permission."""
        team = Team("BRS", "brs", "web")
        test_user = User("userid")
        self.db.retrieve.return_value = test_user
        self.db.query.return_value = [team]
        self.assertTupleEqual(self.testcommand.handle("team delete brs", user),
                              (self.testcommand.permission_error, 200))
        self.db.delete.assert_not_called()
        self.gh.org_delete_team.assert_not_called()

    def test_handle_delete_lookup_error(self):
        """Test team command delete parser with lookup error."""
        self.db.query.return_value = []
        self.assertTupleEqual(self.testcommand.handle("team delete brs", user),
                              (self.testcommand.lookup_error, 200))
        self.db.delete.assert_not_called()
        self.gh.org_delete_team.assert_not_called()

    def test_handle_delete_github_error(self):
        """Test team command delete parser with Github error."""
        self.db.query.side_effect = GithubAPIException("error")
        self.assertTupleEqual(self.testcommand.handle("team delete brs", user),
                              ("Team delete was unsuccessful with "
                               "the following error: "
                               "error", 200))
        self.db.delete.assert_not_called()
        self.gh.org_delete_team.assert_not_called()

    def test_handle_delete(self):
        """Test team command delete parser."""
        team = Team("BRS", "brs", "web")
        team.github_team_id = "12345"
        test_user = User("userid")
        test_user.github_id = "1234"
        team.add_team_lead("1234")
        self.db.retrieve.return_value = test_user
        self.db.query.return_value = [team]
        self.assertTupleEqual(self.testcommand.handle("team delete brs", user),
                              (f"Team brs deleted", 200))
        self.db.delete.assert_called_once_with(Team, "12345")
        self.gh.org_delete_team.assert_called_once_with(int("12345"))

    def test_handle_create(self):
        """Test team command create parser."""
        test_user = User("userid")
        test_user.permissions_level = Permissions.admin
        test_user.github_username = "******"
        self.db.retrieve.return_value = test_user
        self.gh.org_create_team.return_value = "team_id"
        inputstring = "team create b-s --name 'B S'"
        outputstring = "New team created: b-s, name: B S, "
        self.assertTupleEqual(self.testcommand.handle(inputstring, user),
                              (outputstring, 200))
        inputstring += " --platform web"
        outputstring += "platform: web, "
        self.assertTupleEqual(self.testcommand.handle(inputstring, user),
                              (outputstring, 200))
        self.gh.org_create_team.assert_called()
        self.gh.add_team_member.assert_called_with('githubuser', 'team_id')
        inputstring += " --channel 'channelID'"
        outputstring += "added channel, "
        self.sc.get_channel_users.return_value = ['someID', 'otherID']
        self.assertTupleEqual(self.testcommand.handle(inputstring, user),
                              (outputstring, 200))
        self.sc.get_channel_users.assert_called_once_with("channelID")
        self.db.retrieve.assert_called_with(User, 'otherID')
        self.gh.add_team_member.assert_called()
        inputstring += " --lead 'someID'"
        outputstring += "added lead"
        self.gh.has_team_member.return_value = False
        print(self.testcommand.handle(inputstring, user))
        self.assertTupleEqual(self.testcommand.handle(inputstring, user),
                              (outputstring, 200))
        self.db.store.assert_called()

    def test_handle_create_not_admin(self):
        """Test team command create parser with improper permission."""
        test_user = User("userid")
        test_user.github_username = "******"
        self.db.retrieve.return_value = test_user
        self.gh.org_create_team.return_value = "team_id"
        inputstring = "team create b-s --name 'B S'"
        self.assertTupleEqual(self.testcommand.handle(inputstring, user),
                              (self.testcommand.permission_error, 200))
        self.db.store.assert_not_called()

    def test_handle_create_github_error(self):
        """Test team command create parser with Github error."""
        test_user = User("userid")
        test_user.permissions_level = Permissions.admin
        test_user.github_username = "******"
        self.db.retrieve.return_value = test_user
        self.gh.org_create_team.return_value = "team_id"
        inputstring = "team create b-s --name 'B S'"
        self.gh.add_team_member.side_effect = GithubAPIException("error")
        self.assertTupleEqual(self.testcommand.handle(inputstring, user),
                              ("Team creation unsuccessful with the "
                               "following error: error", 200))
        self.db.store.assert_not_called()

    def test_handle_create_lookup_error(self):
        """Test team command create parser with Lookup error."""
        test_user = User("userid")
        test_user.permissions_level = Permissions.admin
        test_user.github_username = "******"
        self.db.retrieve.return_value = test_user
        self.gh.org_create_team.return_value = "team_id"
        inputstring = "team create b-s --name 'B S'"
        self.db.retrieve.side_effect = LookupError
        self.assertTupleEqual(self.testcommand.handle(inputstring, user),
                              (self.testcommand.lookup_error, 200))
        self.db.store.assert_not_called()

    def test_handle_add(self):
        """Test team command add parser."""
        test_user = User("userid")
        test_user.permissions_level = Permissions.admin
        test_user.github_username = "******"
        team = Team("BRS", "brs", "web")
        team.github_team_id = "githubid"
        add_user = User("anotheruser")
        add_user.github_username = "******"
        add_user.github_id = "otherID"
        self.db.retrieve.side_effect = [test_user, add_user]
        self.db.query.return_value = [team]
        with self.app.app_context():
            resp, code = self.testcommand.handle("team add brs ID", user)
            team_attach = team.get_attachment()
            expect = {'attachments': [team_attach],
                      'text': 'Added User to brs'}
            self.assertDictEqual(resp, expect)
            self.assertEqual(code, 200)
        self.db.store.assert_called_with(team)
        assert team.has_member("otherID")
        self.gh.add_team_member.assert_called_once_with("myuser", "githubid")

    def test_handle_add_not_admin(self):
        """Test team command add parser with insufficient permission."""
        test_user = User("userid")
        test_user.github_username = "******"
        team = Team("BRS", "brs", "web")
        team.github_team_id = "githubid"
        self.db.retrieve.return_value = test_user
        self.db.query.return_value = [team]
        self.assertTupleEqual(self.testcommand.handle("team add brs ID", user),
                              (self.testcommand.permission_error, 200))
        self.db.store.assert_not_called()
        self.gh.add_team_member.assert_not_called()

    def test_handle_add_github_error(self):
        """Test team command add parser with Github Exception."""
        test_user = User("userid")
        test_user.github_username = "******"
        test_user.permissions_level = Permissions.admin
        team = Team("BRS", "brs", "web")
        team.github_team_id = "githubid"
        add_user = User("anotheruser")
        add_user.github_username = "******"
        self.db.retrieve.side_effect = [test_user, add_user]
        self.db.query.return_value = [team]
        self.gh.add_team_member.side_effect = GithubAPIException("error")
        self.assertTupleEqual(self.testcommand.handle("team add brs ID", user),
                              ("User added unsuccessfully with the"
                               " following error: error", 200))
        self.db.store.assert_not_called()

    def test_handle_add_lookup_error(self):
        """Test team command parser with lookup error."""
        self.db.retrieve.side_effect = LookupError
        self.assertTupleEqual(self.testcommand.handle("team add brs ID", user),
                              (self.testcommand.lookup_error, 200))
        self.db.store.assert_not_called()
        self.gh.add_team_member.assert_not_called()

    def test_handle_remove(self):
        """Test team command remove parser."""
        test_user = User("userid")
        test_user.permissions_level = Permissions.admin
        test_user.github_username = "******"
        team = Team("BRS", "brs", "web")
        team.github_team_id = "githubid"
        other_user = User("anotheruser")
        other_user.github_id = "githubID"
        other_user.github_username = "******"
        self.db.retrieve.side_effect = [test_user, other_user,
                                        test_user, other_user]
        self.db.query.return_value = [team]
        team_attach = [team.get_attachment()]
        with self.app.app_context():
            self.testcommand.handle("team add brs ID", user)
            resp, code = self.testcommand.handle("team remove brs ID", user)
            expect = {'attachments': team_attach,
                      'text': 'Removed ' 'User from brs'}
            self.assertDictEqual(resp, expect)
            self.assertEqual(code, 200)
        self.db.store.assert_called_with(team)
        self.gh.remove_team_member.assert_called_once_with("myuser",
                                                           "githubid")

    def test_handle_remove_not_in_team(self):
        """Test team command remove parser when user is not in team."""
        test_user = User("userid")
        test_user.permissions_level = Permissions.admin
        team = Team("BRS", "brs", "web")
        team.github_team_id = "githubid"
        other_user = User("anotheruser")
        other_user.github_id = "githubID"
        other_user.github_username = "******"
        self.db.retrieve.side_effect = [test_user, other_user]
        self.db.query.return_value = [team]
        self.gh.has_team_member.return_value = False
        with self.app.app_context():
            self.assertTupleEqual(self.testcommand.handle("team remove"
                                                          " brs ID", user),
                                  ("User not in team!", 200))
        self.gh.has_team_member.assert_called_once_with("myuser", "githubid")
        self.db.store.assert_not_called()
        self.gh.remove_team_member.assert_not_called()

    def test_handle_remove_not_admin(self):
        """Test team command remove parser with insufficient permission."""
        test_user = User("userid")
        team = Team("BRS", "brs", "web")
        self.db.retrieve.return_value = test_user
        self.db.query.return_value = [team]
        with self.app.app_context():
            self.assertTupleEqual(self.testcommand.handle("team remove"
                                                          " brs ID", user),
                                  (self.testcommand.permission_error, 200))
        self.db.store.assert_not_called()
        self.gh.remove_team_member.assert_not_called()

    def test_handle_remove_lookup_error(self):
        """Test team command remove parser with lookup error."""
        test_user = User("userid")
        test_user.permissions_level = Permissions.admin
        self.db.retrieve.side_effect = LookupError
        with self.app.app_context():
            self.assertTupleEqual(self.testcommand.handle("team remove"
                                                          " brs ID", user),
                                  (self.testcommand.lookup_error, 200))
        self.db.store.assert_not_called()
        self.gh.remove_team_member.assert_not_called()

    def test_handle_remove_github_error(self):
        """Test team command remove parser with github error."""
        test_user = User("userid")
        test_user.permissions_level = Permissions.admin
        team = Team("BRS", "brs", "web")
        other_user = User("anotheruser")
        other_user.github_id = "githubID"
        other_user.github_username = "******"
        self.db.retrieve.side_effect = [test_user, other_user]
        self.db.query.return_value = [team]
        self.gh.has_team_member.side_effect = GithubAPIException("error")
        with self.app.app_context():
            self.assertTupleEqual(self.testcommand.handle("team remove"
                                                          " brs ID", user),
                                  ("User removed unsuccessfully with the "
                                   "following error: error", 200))
        self.db.store.assert_not_called()
        self.gh.remove_team_member.assert_not_called()

    def test_handle_lead(self):
        """Test team command lead parser with add and remove options."""
        test_user = User("userid")
        test_user.permissions_level = Permissions.admin
        test_user.github_username = "******"
        team = Team("BRS", "brs", "web")
        team.github_team_id = "githubid"
        other_user = User("anotheruser")
        other_user.github_id = "githubID"
        other_user.github_username = "******"
        self.db.retrieve.side_effect = [test_user, other_user,
                                        test_user, other_user]
        self.db.query.return_value = [team]
        team.add_member("githubID")
        team_before_attach = [team.get_attachment()]
        team.add_team_lead("githubID")
        team_attach = [team.get_attachment()]
        team.discard_member("githubID")
        with self.app.app_context():
            resp, code = self.testcommand.handle("team lead brs ID", user)
            expect = {'attachments': team_attach,
                      'text': 'User added ' 'as team lead to brs'}
            self.assertDictEqual(resp, expect)
            self.assertEqual(code, 200)
            assert team.has_member("githubID")
            self.gh.add_team_member.assert_called_once_with("myuser",
                                                            "githubid")
            self.db.store.assert_called()
            resp, code = self.testcommand.handle("team lead  "
                                                 "--remove brs ID", user)
            expect = {'attachments': team_before_attach,
                      'text': 'User removed as team lead' ' from brs'}
            self.assertDictEqual(resp, expect)
            self.assertEqual(code, 200)
            assert not team.has_team_lead("githubID")
            self.db.store.assert_called()

    def test_handle_lead_not_admin(self):
        """Test team command lead parser with insufficient permission."""
        test_user = User("userid")
        team = Team("BRS", "brs", "web")
        self.db.retrieve.return_value = test_user
        self.db.query.return_value = [team]
        with self.app.app_context():
            self.assertTupleEqual(self.testcommand.handle("team "
                                                          "lead brs ID", user),
                                  (self.testcommand.permission_error, 200))
        self.db.store.assert_not_called()

    def test_handle_lead_lookup_error(self):
        """Test team command laed parser with lookup error."""
        self.db.retrieve.side_effect = LookupError
        with self.app.app_context():
            self.assertTupleEqual(self.testcommand.handle("team lead"
                                                          " brs ID", user),
                                  (self.testcommand.lookup_error, 200))
        self.db.store.assert_not_called()

    def test_handle_lead_github_error(self):
        """Test team command lead parser with github error."""
        test_user = User("userid")
        test_user.permissions_level = Permissions.admin
        team = Team("BRS", "brs", "web")
        self.db.retrieve.side_effect = [test_user, test_user]
        self.db.query.return_value = [team]
        self.gh.add_team_member.side_effect = GithubAPIException("error")
        with self.app.app_context():
            self.assertTupleEqual(self.testcommand.handle("team lead brs ID",
                                                          user),
                                  ("Edit team lead was unsuccessful with the "
                                   "following error: error", 200))
        self.db.store.assert_not_called()

    def test_handle_lead_user_error(self):
        """Test team command lead remove parser with user not in team."""
        test_user = User("userid")
        test_user.permissions_level = Permissions.admin
        team = Team("BRS", "brs", "web")
        self.db.retrieve.side_effect = [test_user, test_user]
        self.db.query.return_value = [team]
        with self.app.app_context():
            self.assertTupleEqual(self.testcommand.handle("team lead "
                                                          "--remove brs"
                                                          " ID", user),
                                  ("User not in team!", 200))
        self.db.store.assert_not_called()

    def test_handle_edit(self):
        """Test team command edit parser."""
        test_user = User("userid")
        test_user.permissions_level = Permissions.admin
        team = Team("BRS", "brs", "brS")
        team.platform = "web"
        team_attach = [team.get_attachment()]
        team.platform = "iOS"
        team.display_name = "b-s"
        self.db.retrieve.return_value = test_user
        self.db.query.return_value = [team]
        with self.app.app_context():
            resp, code = self.testcommand.handle("team edit brs "
                                                 "--name brS "
                                                 "--platform web", user)
            expect = {'attachments': team_attach,
                      'text': 'Team edited: brs, '
                      'name: brS, '
                      'platform: web'}
            self.assertDictEqual(resp, expect)
            self.assertEqual(code, 200)
            self.db.store.assert_called_once_with(team)

    def test_handle_edit_not_admin(self):
        """Test team command edit parser with insufficient permission."""
        test_user = User("userid")
        team = Team("BRS", "brs", "brS")
        self.db.retrieve.return_value = test_user
        self.db.query.return_value = [team]
        with self.app.app_context():
            self.assertTupleEqual(self.testcommand.handle("team "
                                                          "edit brs", user),
                                  (self.testcommand.permission_error, 200))
        self.db.store.assert_not_called()

    def test_handle_edit_lookup_error(self):
        """Test team command edit parser with lookup error."""
        self.db.query.return_value = []
        with self.app.app_context():
            self.assertTupleEqual(self.testcommand.handle("team "
                                                          "edit brs", user),
                                  (self.testcommand.lookup_error, 200))
        self.db.store.assert_not_called()

    def test_handle_refresh_not_admin(self):
        """Test team command refresh parser with insufficient permission."""
        test_user = User(user)
        self.db.retrieve.return_value = test_user
        with self.app.app_context():
            self.assertTupleEqual(self.testcommand.handle("team refresh",
                                                          user),
                                  (self.testcommand.permission_error, 200))
        self.db.store.assert_not_called()

    def test_handle_refresh_lookup_error(self):
        """Test team command refresh parser with lookup error."""
        test_user = User(user)
        team = Team("BRS", "brs", "brS")
        test_user.permissions_level = Permissions.admin
        self.db.retrieve.return_value = None
        self.db.retrieve.side_effect = LookupError
        self.gh.org_get_teams.return_value = [team]
        with self.app.app_context():
            self.assertTupleEqual(self.testcommand.handle("team refresh",
                                                          user),
                                  (self.testcommand.lookup_error, 200))
        self.db.store.assert_not_called()

    def test_handle_refresh_github_error(self):
        """Test team command refresh parser with github error."""
        test_user = User(user)
        test_user.permissions_level = Permissions.admin
        self.db.retrieve.return_value = test_user
        self.gh.org_get_teams.side_effect = GithubAPIException("error")
        with self.app.app_context():
            self.assertTupleEqual(self.testcommand.handle("team refresh",
                                                          user),
                                  ("Refresh teams was unsuccessful with "
                                   "the following error: error", 200))
        self.db.store.assert_not_called()

    def test_handle_refresh_changed(self):
        """Test team command refresh parser if team edited in github."""
        test_user = User(user)
        test_user.permissions_level = Permissions.admin
        team = Team("TeamID", "TeamName", "android")
        team_update = Team("TeamID", "new team name", "android")
        team_update.add_member(test_user.github_id)
        team2 = Team("OTEAM", "other team2", "ios")

        self.db.retrieve.return_value = test_user
        self.db.query.return_value = [team, team2]
        self.gh.org_get_teams.return_value = [team_update, team2]
        attach = team_update.get_attachment()

        status = f"1 teams changed, " \
            f"0 added, " \
            f"0 deleted. Wonderful."
        with self.app.app_context():
            resp, code = self.testcommand.handle("team refresh", user)
            expect = {'attachments': [attach], 'text': status}
            self.assertDictEqual(resp, expect)
            self.assertEqual(code, 200)
        self.db.query.assert_called_once_with(Team)

    def test_handle_refresh_addition_and_deletion(self):
        """Test team command refresh parser if local differs from github."""
        test_user = User(user)
        test_user.permissions_level = Permissions.admin
        team = Team("TeamID", "TeamName", "")
        team2 = Team("OTEAM", "other team", "android")

        self.db.retrieve.return_value = test_user
        self.db.query.return_value = [team2]

        # In this case, github does not have team2!
        self.gh.org_get_teams.return_value = [team]
        attach = team.get_attachment()
        attach2 = team2.get_attachment()

        status = f"0 teams changed, " \
            f"1 added, " \
            f"1 deleted. Wonderful."
        with self.app.app_context():
            resp, code = self.testcommand.handle("team refresh", user)
            expect = {'attachments': [attach2, attach], 'text': status}
            self.assertDictEqual(resp, expect)
            self.assertEqual(code, 200)
        self.db.query.assert_called_once_with(Team)
Esempio n. 2
0
class TestTeamCommand(TestCase):
    def setUp(self):
        self.app = Flask(__name__)
        self.config = mock.MagicMock()
        self.gh = mock.MagicMock()

        self.u0 = User('U123456789')
        self.u1 = User('U234567891')
        self.admin = create_test_admin('Uadmin')
        self.t0 = Team("BRS", "brs", "web")
        self.t1 = Team("OTEAM", "other team", "android")
        self.t2 = Team("LEADS", "leads", "")
        self.t3 = Team("ADMIN", "admin", "")
        self.db = MemoryDB(users=[self.u0, self.u1, self.admin],
                           teams=[self.t0, self.t1, self.t2, self.t3])

        self.sc = mock.MagicMock()
        self.testcommand = TeamCommand(self.config, self.db, self.gh, self.sc)
        self.help_text = self.testcommand.help
        self.maxDiff = None

        self.config.github_team_all = 'all'
        self.config.github_team_leads = 'leads'
        self.config.github_team_admin = 'admin'

    def test_get_help(self):
        subcommands = list(self.testcommand.subparser.choices.keys())
        help_message = self.testcommand.get_help()
        self.assertEqual(len(subcommands), help_message.count("usage"))

    def test_get_subcommand_help(self):
        subcommands = list(self.testcommand.subparser.choices.keys())
        for subcommand in subcommands:
            help_message = self.testcommand.get_help(subcommand=subcommand)
            self.assertEqual(1, help_message.count("usage"))

    def test_get_invalid_subcommand_help(self):
        """Test team command get_help method for invalid subcommands."""
        self.assertEqual(self.testcommand.get_help(),
                         self.testcommand.get_help(subcommand="foo"))

    def test_handle_help(self):
        ret, code = self.testcommand.handle("team help", self.u0.slack_id)
        self.assertEqual(ret, self.testcommand.get_help())
        self.assertEqual(code, 200)

    def test_handle_multiple_subcommands(self):
        """Test handling multiple observed subcommands."""
        ret, code = self.testcommand.handle("team list edit", self.u0.slack_id)
        self.assertEqual(ret, self.testcommand.get_help())
        self.assertEqual(code, 200)

    def test_handle_subcommand_help(self):
        """Test team subcommand help text."""
        subcommands = list(self.testcommand.subparser.choices.keys())
        for subcommand in subcommands:
            for arg in ['--help', '-h', '--invalid argument']:
                command = f"team {subcommand} {arg}"
                ret, code = self.testcommand.handle(command, self.u0.slack_id)
                self.assertEqual(1, ret.count("usage"))
                self.assertEqual(code, 200)

    def test_handle_list(self):
        attachment = [
            self.t0.get_basic_attachment(),
            self.t1.get_basic_attachment(),
            self.t2.get_basic_attachment(),
            self.t3.get_basic_attachment(),
        ]
        with self.app.app_context():
            resp, code = self.testcommand.handle('team list', self.u0.slack_id)
            expect = {'attachments': attachment}
            self.assertDictEqual(resp, expect)
            self.assertEqual(code, 200)

    def test_handle_list_no_teams(self):
        self.db.teams = {}
        self.assertTupleEqual(
            self.testcommand.handle('team list', self.u0.slack_id),
            ('No Teams Exist!', 200))

    def test_handle_view(self):
        with self.app.app_context():
            resp, code = self.testcommand.handle('team view brs',
                                                 self.u0.slack_id)
            expect = {'attachments': [self.t0.get_attachment()]}
            self.assertDictEqual(resp, expect)
            self.assertEqual(code, 200)

    def test_handle_view_lookup_error(self):
        self.assertTupleEqual(
            self.testcommand.handle('team view iesesebrs', self.u0.slack_id),
            (self.testcommand.lookup_error, 200))

    def test_handle_view_noleads(self):
        resp, code = self.testcommand.handle('team view brs', self.u0.slack_id)
        self.assertDictEqual(resp['attachments'][0], self.t0.get_attachment())
        self.assertEqual(code, 200)

    def test_handle_delete_not_admin(self):
        self.assertTupleEqual(
            self.testcommand.handle('team delete brs', self.u0.slack_id),
            (self.testcommand.permission_error, 200))
        self.gh.org_delete_team.assert_not_called()

    def test_handle_delete_lookup_error(self):
        self.assertTupleEqual(
            self.testcommand.handle('team delete brs', 'ioenairsetno'),
            (self.testcommand.lookup_error, 200))
        self.gh.org_delete_team.assert_not_called()

    def test_handle_delete_github_error(self):
        self.t0.github_team_id = '123452'
        self.gh.org_delete_team.side_effect = GithubAPIException('error')
        self.assertTupleEqual(
            self.testcommand.handle('team delete brs', self.admin.slack_id),
            ('Team delete was unsuccessful with '
             'the following error: '
             'error', 200))

    def test_handle_delete(self):
        self.t0.github_team_id = '12345'
        self.u0.github_id = '132432'
        self.u0.permissions_level = Permissions.team_lead
        self.t0.add_team_lead(self.u0.github_id)
        self.assertTupleEqual(
            self.testcommand.handle('team delete brs', self.u0.slack_id),
            ('Team brs deleted', 200))
        self.gh.org_delete_team.assert_called_once_with(int('12345'))

    def test_handle_create(self):
        self.gh.org_create_team.return_value = '8934095'
        inputstring = "team create b-s --name 'B S'"
        outputstring = 'New team created: b-s, name: B S, '
        self.assertTupleEqual(
            self.testcommand.handle(inputstring, self.admin.slack_id),
            (outputstring, 200))
        inputstring += ' --platform web'
        outputstring += 'platform: web, '
        self.assertTupleEqual(
            self.testcommand.handle(inputstring, self.admin.slack_id),
            (outputstring, 200))
        self.gh.org_create_team.assert_called()
        self.gh.add_team_member.assert_called_with(self.admin.github_username,
                                                   '8934095')

        inputstring += " --channel 'channelID'"
        outputstring += "added channel, "
        self.sc.get_channel_users.return_value = ['someID', 'otherID']
        self.assertTupleEqual(
            self.testcommand.handle(inputstring, self.admin.slack_id),
            (outputstring, 200))
        self.sc.get_channel_users.assert_called_once_with('channelID')
        self.gh.add_team_member.assert_called()
        inputstring += f' --lead {self.u0.slack_id}'
        outputstring += 'added lead'
        self.gh.has_team_member.return_value = False
        self.assertTupleEqual(
            self.testcommand.handle(inputstring, self.admin.slack_id),
            (outputstring, 200))

    def test_handle_create_not_admin(self):
        self.u0.github_username = '******'
        self.u0.github_id = '12'
        self.gh.org_create_team.return_value = 'team_id'
        inputstring = "team create b-s --name 'B S'"
        self.assertTupleEqual(
            self.testcommand.handle(inputstring, self.u0.slack_id),
            (self.testcommand.permission_error, 200))

    def test_handle_create_not_ghuser(self):
        self.u0.permissions_level = Permissions.admin
        self.gh.org_create_team.return_value = 'team_id'
        s = 'team create someting'
        ret, val = self.testcommand.handle(s, self.u0.slack_id)
        self.assertEqual(val, 200)
        self.assertIn('yet to register', ret)

    def test_handle_create_github_error(self):
        self.gh.org_create_team.return_value = 'team_id'
        inputstring = "team create b-s --name 'B S'"
        self.gh.add_team_member.side_effect = GithubAPIException('error')
        self.assertTupleEqual(
            self.testcommand.handle(inputstring, self.admin.slack_id),
            ('Team creation unsuccessful with the '
             'following error: error', 200))

    def test_handle_create_lookup_error(self):
        inputstring = "team create b-s --name 'B S'"
        self.assertTupleEqual(self.testcommand.handle(inputstring, 'rando'),
                              (self.testcommand.lookup_error, 200))

    def test_handle_add(self):
        self.t0.github_team_id = 'githubid'
        self.u0.github_username = '******'
        self.u0.github_id = 'otherID'
        with self.app.app_context():
            resp, code = self.testcommand.handle(
                f'team add brs {self.u0.slack_id}', self.admin.slack_id)
            expect = {
                'attachments': [self.t0.get_attachment()],
                'text': 'Added User to brs'
            }
            self.assertDictEqual(resp, expect)
            self.assertEqual(code, 200)
        self.assertTrue(self.t0.has_member("otherID"))
        self.gh.add_team_member.assert_called_once_with('myuser', 'githubid')

    def test_handle_add_but_forgot_githubid(self):
        self.t0.github_team_id = 'githubid'
        self.gh.add_team_member.side_effect = GithubAPIException('error')
        self.assertTupleEqual(
            self.testcommand.handle(f'team add brs {self.u0.slack_id}',
                                    self.admin.slack_id),
            (TeamCommand.no_ghusername_error, 200))

    def test_handle_add_not_admin(self):
        """Test team command add parser with insufficient permission."""
        self.t0.github_team_id = 'githubid'
        self.assertTupleEqual(
            self.testcommand.handle(f'team add brs {self.u1.slack_id}',
                                    self.u0.slack_id),
            (self.testcommand.permission_error, 200))
        self.gh.add_team_member.assert_not_called()

    def test_handle_add_github_error(self):
        self.t0.github_team_id = 'githubid'
        self.u0.github_id = 'myuser'
        self.gh.add_team_member.side_effect = GithubAPIException('error')
        self.assertTupleEqual(
            self.testcommand.handle(f'team add brs {self.u0.slack_id}',
                                    self.admin.slack_id),
            ('User added unsuccessfully with the'
             ' following error: error', 200))

    def test_handle_add_lookup_error(self):
        self.assertTupleEqual(
            self.testcommand.handle('team add brs ID', 'rando'),
            (self.testcommand.lookup_error, 200))
        self.gh.add_team_member.assert_not_called()

    def test_handle_add_promote(self):
        self.u0.github_username = '******'
        self.u0.github_id = 'otherID'
        self.t2.github_team_id = 'githubid'
        with self.app.app_context():
            resp, code = self.testcommand.handle(
                f'team add leads {self.u0.slack_id}', self.admin.slack_id)
            expect_msg = 'Added User to leads and promoted user to team_lead'
            expect = {
                'attachments': [self.t2.get_attachment()],
                'text': expect_msg
            }
            self.assertDictEqual(resp, expect)
            self.assertEqual(code, 200)
        self.assertTrue(self.t2.has_member("otherID"))
        self.assertEquals(self.u0.permissions_level, Permissions.team_lead)
        self.gh.add_team_member.assert_called_once_with('myuser', 'githubid')

    def test_handle_add_promote_current_admin(self):
        self.u0.github_username = '******'
        self.u0.github_id = 'otherID'
        self.t2.github_team_id = 'githubid'
        # existing admin member should not be "promoted" to lead
        self.u0.permissions_level = Permissions.admin
        self.t3.add_member(self.u0.github_id)
        with self.app.app_context():
            resp, code = self.testcommand.handle(
                f'team add leads {self.u0.slack_id}', self.admin.slack_id)
            expect_msg = 'Added User to leads'
            expect = {
                'attachments': [self.t2.get_attachment()],
                'text': expect_msg
            }
            self.assertDictEqual(resp, expect)
            self.assertEqual(code, 200)
        self.assertTrue(self.t2.has_member("otherID"))
        self.assertEquals(self.u0.permissions_level, Permissions.admin)
        self.gh.add_team_member.assert_called_once_with('myuser', 'githubid')

    def test_handle_remove(self):
        self.u0.github_id = 'githubID'
        self.u0.github_username = '******'
        self.t0.add_member(self.u0.github_id)
        with self.app.app_context():
            resp, code = self.testcommand.handle(
                f'team remove {self.t0.github_team_name} {self.u0.slack_id}',
                self.admin.slack_id)
            expect = {
                'attachments': [self.t0.get_attachment()],
                'text': f'Removed User from {self.t0.github_team_name}'
            }
            self.assertDictEqual(resp, expect)
            self.assertEqual(code, 200)
        self.gh.remove_team_member.assert_called_once_with(
            self.u0.github_username, self.t0.github_team_id)

    def test_handle_remove_user_not_in_team(self):
        """Test team command remove parser when user is not in team."""
        self.u0.github_id = 'githubID'
        self.u0.github_username = '******'
        self.gh.has_team_member.return_value = False
        with self.app.app_context():
            self.assertTupleEqual(
                self.testcommand.handle(
                    f'team remove {self.t0.github_team_name} {self.u0.slack_id}',
                    self.admin.slack_id), ("User not in team!", 200))
        self.gh.has_team_member.assert_called_once_with(
            self.u0.github_username, self.t0.github_team_id)
        self.gh.remove_team_member.assert_not_called()

    def test_handle_remove_demote(self):
        self.u0.github_username = '******'
        self.u0.github_id = 'otherID'
        self.t2.add_member(self.u0.github_id)
        with self.app.app_context():
            resp, code = self.testcommand.handle(
                f'team remove leads {self.u0.slack_id}', self.admin.slack_id)
            expect_msg = 'Removed User from leads and demoted user'
            expect = {
                'attachments': [self.t2.get_attachment()],
                'text': expect_msg
            }
            self.assertDictEqual(resp, expect)
            self.assertEqual(code, 200)
        self.assertEquals(self.u0.permissions_level, Permissions.member)
        self.gh.remove_team_member.assert_called_once_with(
            self.u0.github_username, self.t2.github_team_id)

    def test_handle_remove_demote_to_team_lead(self):
        self.u0.github_username = '******'
        self.u0.github_id = 'otherID'
        self.t2.add_member(self.u0.github_id)
        self.t3.add_member(self.u0.github_id)
        with self.app.app_context():
            resp, code = self.testcommand.handle(
                f'team remove admin {self.u0.slack_id}', self.admin.slack_id)
            expect_msg = 'Removed User from admin and demoted user'
            expect = {
                'attachments': [self.t3.get_attachment()],
                'text': expect_msg
            }
            self.assertDictEqual(resp, expect)
            self.assertEqual(code, 200)
        self.assertEquals(self.u0.permissions_level, Permissions.team_lead)
        self.gh.remove_team_member.assert_called_once_with(
            self.u0.github_username, self.t3.github_team_id)

    def test_handle_remove_demote_to_admin(self):
        self.u0.github_username = '******'
        self.u0.github_id = 'otherID'
        self.u0.permissions_level = Permissions.admin
        self.t2.add_member(self.u0.github_id)
        self.t3.add_member(self.u0.github_id)
        with self.app.app_context():
            # Leads member should not be demoted if they are also a admin
            # member
            resp, code = self.testcommand.handle(
                f'team remove leads {self.u0.slack_id}', self.admin.slack_id)
            expect_msg = 'Removed User from leads'
            expect = {
                'attachments': [self.t2.get_attachment()],
                'text': expect_msg
            }
            self.assertDictEqual(resp, expect)
            self.assertEqual(code, 200)
        self.assertEquals(self.u0.permissions_level, Permissions.admin)
        self.gh.remove_team_member.assert_called_once_with(
            self.u0.github_username, self.t2.github_team_id)

    def test_handle_remove_not_admin(self):
        with self.app.app_context():
            self.assertTupleEqual(
                self.testcommand.handle(
                    f'team remove {self.t0.github_team_name} {self.u0.slack_id}',
                    self.u1.slack_id),
                (self.testcommand.permission_error, 200))
        self.gh.remove_team_member.assert_not_called()

    def test_handle_remove_lookup_error(self):
        with self.app.app_context():
            self.assertTupleEqual(
                self.testcommand.handle(
                    f'team remove {self.t0.github_team_name} {self.u0.slack_id}',
                    'another.rando'), (self.testcommand.lookup_error, 200))
        self.gh.remove_team_member.assert_not_called()

    def test_handle_remove_github_error(self):
        self.gh.has_team_member.side_effect = GithubAPIException('error')
        with self.app.app_context():
            self.assertTupleEqual(
                self.testcommand.handle(
                    f'team remove {self.t0.github_team_name} {self.u0.slack_id}',
                    self.admin.slack_id),
                ('User removed unsuccessfully with the '
                 'following error: error', 200))
        self.gh.remove_team_member.assert_not_called()

    def test_handle_lead_add(self):
        self.u0.github_id = 'githubID'
        self.u0.github_username = '******'
        with self.app.app_context():
            self.assertFalse(self.t0.has_team_lead(self.u0.github_id))
            self.assertFalse(self.t0.has_member(self.u0.github_id))
            _, code = self.testcommand.handle(
                f'team lead {self.t0.github_team_name} {self.u0.slack_id}',
                self.admin.slack_id)
            self.assertEqual(code, 200)
            self.assertTrue(self.t0.has_team_lead(self.u0.github_id))
            self.assertTrue(self.t0.has_member(self.u0.github_id))
            self.gh.add_team_member.assert_called_once_with(
                self.u0.github_username, self.t0.github_team_id)

    def test_handle_lead_remove(self):
        self.u0.github_id = 'githubID'
        self.u0.github_username = '******'
        self.t0.add_member(self.u0.github_id)
        self.t0.add_team_lead(self.u0.github_id)
        with self.app.app_context():
            self.assertTrue(self.t0.has_team_lead(self.u0.github_id))
            _, code = self.testcommand.handle(
                f'team lead --remove {self.t0.github_team_name}'
                f' {self.u0.slack_id}', self.admin.slack_id)
            self.assertEqual(code, 200)
            self.assertFalse(self.t0.has_team_lead(self.u0.github_id))

    def test_handle_lead_not_admin(self):
        with self.app.app_context():
            self.assertTupleEqual(
                self.testcommand.handle(
                    f'team lead {self.t0.github_team_name} {self.u0.slack_id}',
                    self.u1.slack_id),
                (self.testcommand.permission_error, 200))

    def test_handle_lead_lookup_error(self):
        with self.app.app_context():
            self.assertTupleEqual(
                self.testcommand.handle(
                    f'team lead {self.t0.github_team_name} {self.u0.slack_id}',
                    'rando.rand'), (self.testcommand.lookup_error, 200))

    def test_handle_lead_github_error(self):
        self.gh.add_team_member.side_effect = GithubAPIException('error')
        with self.app.app_context():
            self.assertTupleEqual(
                self.testcommand.handle(
                    f'team lead {self.t0.github_team_name} {self.u0.slack_id}',
                    self.admin.slack_id),
                ('Edit team lead was unsuccessful with the '
                 'following error: error', 200))

    def test_handle_lead_user_error(self):
        with self.app.app_context():
            self.assertTupleEqual(
                self.testcommand.handle(
                    f'team lead --remove {self.t0.github_team_name}'
                    f' {self.u0.slack_id}', self.admin.slack_id),
                ('User not in team!', 200))

    def test_handle_edit(self):
        with self.app.app_context():
            _, code = self.testcommand.handle(
                f'team edit {self.t0.github_team_name}'
                ' --name brS --platform web', self.admin.slack_id)
            self.assertEqual(self.t0.display_name, 'brS')
            self.assertEqual(self.t0.platform, 'web')
            self.assertEqual(code, 200)

    def test_handle_edit_not_admin(self):
        with self.app.app_context():
            self.assertTupleEqual(
                self.testcommand.handle(
                    f'team edit {self.t0.github_team_name}', self.u0.slack_id),
                (self.testcommand.permission_error, 200))

    def test_handle_edit_lookup_error(self):
        with self.app.app_context():
            self.assertTupleEqual(
                self.testcommand.handle('team edit rando.team',
                                        self.admin.slack_id),
                (self.testcommand.lookup_error, 200))

    def test_handle_refresh_not_admin(self):
        with self.app.app_context():
            self.assertTupleEqual(
                self.testcommand.handle('team refresh', self.u0.slack_id),
                (self.testcommand.permission_error, 200))

    def test_handle_refresh_lookup_error(self):
        """Test team command refresh parser with lookup error."""
        with self.app.app_context():
            self.assertTupleEqual(
                self.testcommand.handle('team refresh', 'rando.randy'),
                (self.testcommand.lookup_error, 200))

    def test_handle_refresh_github_error(self):
        self.gh.org_get_teams.side_effect = GithubAPIException('error')
        with self.app.app_context():
            self.assertTupleEqual(
                self.testcommand.handle('team refresh', self.admin.slack_id),
                ('Refresh teams was unsuccessful with '
                 'the following error: error', 200))

    def test_handle_refresh_changed(self):
        """Test team command refresh parser if team edited in github."""
        team = Team('TeamID', 'TeamName', 'android')
        team_update = Team('TeamID', 'new team name', 'android')
        team_update.add_member(self.admin.github_id)
        team2 = Team('OTEAM', 'other team2', 'ios')

        self.db.teams = {}
        self.db.teams['TeamID'] = team
        self.db.teams['OTEAM'] = team2

        self.gh.org_get_teams.return_value = [team_update, team2]
        attach = team_update.get_attachment()

        status = '1 teams changed, 0 added, 0 deleted. Wonderful.'
        with self.app.app_context():
            resp, code = self.testcommand.handle('team refresh',
                                                 self.admin.slack_id)
            expect = {'attachments': [attach], 'text': status}
            self.assertDictEqual(resp, expect)
            self.assertEqual(code, 200)
            self.assertEqual(team, team_update)

    def test_handle_refresh_addition_and_deletion(self):
        """Test team command refresh parser if local differs from github."""
        team = Team('TeamID', 'TeamName', '')
        team2 = Team('OTEAM', 'other team', 'android')

        self.db.teams = {}
        self.db.teams['OTEAM'] = team2

        # In this case, github does not have team2!
        self.gh.org_get_teams.return_value = [team]
        self.gh.org_create_team.return_value = 12345
        attach = team.get_attachment()
        attach2 = team2.get_attachment()

        status = '0 teams changed, 1 added, 1 deleted. Wonderful.'
        with self.app.app_context():
            resp, code = self.testcommand.handle('team refresh',
                                                 self.admin.slack_id)
            expect = {'attachments': [attach2, attach], 'text': status}
            self.assertDictEqual(resp, expect)
            self.assertEqual(code, 200)
            self.assertEqual(len(self.db.teams), 2)