class TestUserCommand(TestCase): def setUp(self): self.app = Flask(__name__) self.u0 = User('U0G9QF9C6') self.u1 = User('Utheomadude') self.admin = create_test_admin('Uadmin') self.db = MemoryDB(users=[self.u0, self.u1, self.admin]) self.mock_github = mock.MagicMock(GithubInterface) self.testcommand = UserCommand(self.db, self.mock_github, None) self.maxDiff = None def test_get_help(self): """Test user 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 user 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 user command get_help method for invalid subcommands.""" self.assertEqual(self.testcommand.get_help(), self.testcommand.get_help(subcommand="foo")) def test_handle_nosubs(self): """Test user with no sub-parsers.""" self.assertEqual(self.testcommand.handle('user', self.u0.slack_id), (self.testcommand.help, 200)) def test_handle_bad_args(self): """Test user with invalid arguments.""" self.assertEqual( self.testcommand.handle('user geese', self.u0.slack_id), (self.testcommand.help, 200)) def test_handle_add(self): """Test user command add method.""" user_id = "U0G9QF9C7" user = User(user_id) self.assertTupleEqual(self.testcommand.handle('user add', user_id), ('User added!', 200)) retr = self.db.retrieve(User, user_id) self.assertEqual(user, retr) def test_handle_add_no_overwriting(self): """Test user command add method when user exists in db.""" user = User(self.u0.slack_id) err_msg = 'User already exists; to overwrite user, add `-f`' resp = self.testcommand.handle('user add', user.slack_id) self.assertTupleEqual(resp, (err_msg, 200)) def test_handle_add_with_force(self): ret = self.testcommand.handle('user add -f', self.u0.slack_id) self.assertEqual(ret, ('User added!', 200)) def test_handle_view(self): user_attaches = [self.u0.get_attachment()] with self.app.app_context(): # jsonify requires translating the byte-string resp, code = self.testcommand.handle('user view', self.u0.slack_id) expect = {'attachments': user_attaches} self.assertDictEqual(resp, expect) self.assertEqual(code, 200) def test_handle_view_other_user(self): user = User("ABCDE8FA9") self.db.store(user) command = 'user view --username ' + user.slack_id user_attaches = [user.get_attachment()] with self.app.app_context(): # jsonify requires translating the byte-string resp, code = self.testcommand.handle(command, self.u0.slack_id) expect = {'attachments': user_attaches} self.assertDictEqual(resp, expect) self.assertEqual(code, 200) def test_handle_view_lookup_error(self): command = 'user view --username ABCDE8FA9' self.assertTupleEqual( self.testcommand.handle(command, self.u0.slack_id), (UserCommand.lookup_error, 200)) def test_handle_help(self): self.assertEqual( self.testcommand.handle('user help', self.u0.slack_id), (self.testcommand.help, 200)) def test_handle_delete(self): message = f'Deleted user with Slack ID: {self.u0.slack_id}' cmd = f'user delete {self.u0.slack_id}' self.assertEqual(self.testcommand.handle(cmd, self.admin.slack_id), (message, 200)) with self.assertRaises(LookupError): self.db.retrieve(User, self.u0.slack_id) def test_handle_delete_not_admin(self): cmd = f'user delete {self.u1.slack_id}' self.assertEqual(self.testcommand.handle(cmd, self.u0.slack_id), (UserCommand.permission_error, 200)) def test_handle_delete_callinguser_lookup_error(self): cmd = f'user delete {self.u1.slack_id}' self.assertEqual(self.testcommand.handle(cmd, 'rando.id'), (UserCommand.lookup_error, 200)) def test_handle_edit_name(self): with self.app.app_context(): resp, code = self.testcommand.handle('user edit --name rob', self.u0.slack_id) expect = {'title': 'Name', 'value': 'rob', 'short': True} self.assertIn(expect, resp['attachments'][0]['fields']) self.assertEqual(code, 200) def test_handle_edit_github(self): """Test that editing github username sends request to interface.""" self.mock_github.org_add_member.return_value = "123" with self.app.app_context(): resp, code = self.testcommand.handle("user edit --github rob", self.u0.slack_id) expect0 = { 'title': 'Github Username', 'value': 'rob', 'short': True } expect1 = {'title': 'Github ID', 'value': '123', 'short': True} self.assertIn(expect0, resp['attachments'][0]['fields']) self.assertIn(expect1, resp['attachments'][0]['fields']) self.assertEqual(code, 200) self.mock_github.org_add_member.assert_called_once_with("rob") def test_handle_edit_github_error(self): self.mock_github.org_add_member.side_effect = GithubAPIException("") with self.app.app_context(): resp, code = self.testcommand.handle('user edit --github rob', self.u0.slack_id) expect = { 'attachments': [self.u0.get_attachment()], 'text': '\nError adding user rob to GitHub organization' } self.assertDictEqual(resp, expect) self.assertEqual(code, 200) def test_handle_edit_all_fields(self): user = User(self.u0.slack_id) user.name = 'rob' user.email = '*****@*****.**' user.position = 'dev' user.github_username = '******' user.github_id = '123' user.major = 'Computer Science' user.biography = 'Im a human lol' user.permissions_level = Permissions.member expect = {'attachments': [user.get_attachment()]} self.mock_github.org_add_member.return_value = "123" with self.app.app_context(): resp, code = self.testcommand.handle( "user edit " "--name rob " "--email <mailto:[email protected]|[email protected]> --pos dev --github" " rob --major 'Computer Science'" " --bio 'Im a human lol'", self.u0.slack_id) self.assertDictEqual(resp, expect) self.assertEqual(code, 200) def test_handle_edit_not_admin(self): """Test user command with editor user that is not admin.""" self.assertEqual( self.testcommand.handle( 'user edit --username ' + self.u1.slack_id + ' ' '--name rob ' '--email <mailto:[email protected]|[email protected]> --pos dev --github' ' [email protected] --major \'Computer Science\'' ' --bio \'Im a human\'', self.u0.slack_id), (UserCommand.permission_error, 200)) def test_handle_edit_make_admin(self): with self.app.app_context(): resp, code = self.testcommand.handle( f"user edit --username {self.u0.slack_id} " "--permission admin", self.admin.slack_id) expect = { 'title': 'Permissions Level', 'value': 'admin', 'short': True } self.assertIn(expect, resp['attachments'][0]['fields']) self.assertEqual(code, 200) def test_handle_edit_make_self_admin_no_perms(self): with self.app.app_context(): resp, code = self.testcommand.handle( "user edit --permission admin", self.u0.slack_id) expect = { 'attachments': [self.u0.get_attachment()], 'text': "\nCannot change own permission: user isn't admin." } self.assertDictEqual(resp, expect) self.assertEqual(code, 200) def test_handle_edit_lookup_error_editee(self): self.assertEqual( self.testcommand.handle( "user edit --username random.something " "--name rob " "--email <mailto:[email protected]|[email protected]> --pos dev --github" " [email protected] --major 'Computer Science'" " --bio 'Im a human'", self.admin.slack_id), (UserCommand.lookup_error, 200)) def test_handle_edit_lookup_error(self): """Test user command where user is not in database.""" self.assertEqual( self.testcommand.handle('user edit --name rob', 'rando'), (UserCommand.lookup_error, 200)) def test_handle_command_help(self): ret, code = self.testcommand.handle('user 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('user edit view', self.u0.slack_id) self.assertEqual(ret, self.testcommand.get_help()) self.assertEqual(code, 200) def test_handle_subcommand_help(self): subcommands = list(self.testcommand.subparser.choices.keys()) for subcommand in subcommands: cmd_args = ['--help', '-h', '--invalid argument'] for arg in cmd_args: command = f'user {subcommand} {arg}' ret, code = self.testcommand.handle(command, self.u0.slack_id) self.assertEqual(1, ret.count("usage")) self.assertIn(subcommand, ret) self.assertEqual(code, 200)
class TestMemoryDB(TestCase): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.admin = util.create_test_admin('Uadmin') self.users = {u.slack_id: u for u in makeUsers(20)} self.users['Uadmin'] = self.admin self.teams = {t.github_team_id: t for t in makeTeams()} def setUp(self): self.db = MemoryDB(users=list(self.users.values()), teams=list(self.teams.values())) def test_get_db_lookup_error(self): with self.assertRaises(LookupError): self.db.get_db(TestMemoryDB) def test_users_dont_affect_DB(self): """ DB modifications shouldn't affect dict outside. Models themselves being modified are okay. But modifying the composition of the DB (which objects are in it) is not. This test makes sure that deleting a user from the DB does not delete it from the user dictionary. """ slack_id = random.choice(list(self.users.keys())) self.db.users.pop(slack_id) self.assertIn(slack_id, self.users) def test_store_valid_user(self): u = User('u3') self.assertTrue(self.db.store(u)) def test_store_invalid_user(self): u = User('') self.assertFalse(self.db.store(u)) def test_retrieve_users_randomly(self): ks = list(self.users.keys()) for _ in range(10): slack_id = random.choice(ks) u = self.db.retrieve(User, slack_id) self.assertEqual(u.github_username, self.users[slack_id].github_username) def test_retrieve_nonexistant_user(self): with self.assertRaises(LookupError): self.db.retrieve(User, 'bad user bad bad') def test_bulk_retrieve(self): selection = random.sample(list(self.users.keys()), k=10) us = self.db.bulk_retrieve(User, selection) self.assertEqual(len(us), 10) for u in us: self.assertEqual(u.github_username, self.users[u.slack_id].github_username) def test_bulk_retrieve_nothing(self): selection = [str(i) for i in range(100)] us = self.db.bulk_retrieve(User, selection) self.assertEqual(us, []) def test_query_team_name(self): ts = self.db.query(Team, [('github_team_name', 'T1')]) self.assertEqual(len(ts), 1) self.assertEqual(ts[0], self.teams['t1']) def test_query_multi_params(self): ts = self.db.query( Team, [('members', 'u0'), ('team_leads', 'u1')]) self.assertEqual(len(ts), 1) self.assertEqual(ts[0], self.teams['t0']) def test_query_multi_teams(self): ts = self.db.query(Team, [('members', 'u0')]) self.assertCountEqual(ts, [self.teams['t0'], self.teams['t1']]) def test_scan_query(self): us = self.db.query(User) self.assertCountEqual(us, list(self.users.values())) def test_query_all_admins(self): admins = self.db.query(User, [('permission_level', 'admin')]) self.assertIn(self.admin, admins) def test_scan_teams(self): ts = self.db.query_or(Team) self.assertCountEqual(ts, list(self.teams.values())) def test_bulk_retrieve_using_query(self): selection = random.sample(list(self.users.items()), k=10) rand_vals = [v for _, v in selection] q_string = [('slack_id', k) for k, _ in selection] us = self.db.query_or(User, q_string) self.assertCountEqual(us, rand_vals) self.assertEqual(len(us), 10) def test_delete_user(self): slack_id = random.choice(list(self.users.keys())) self.db.delete(User, slack_id) with self.assertRaises(LookupError): self.db.retrieve(User, slack_id) def test_displayname(self): ts = self.db.query(Team, [('displayname', 'T Zero Blasters')]) self.assertEqual(len(ts), 1) self.assertEqual(ts[0], self.teams['t0'])