diff --git a/allianceauth/services/modules/mumble/tests/__init__.py b/allianceauth/services/modules/mumble/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/allianceauth/services/modules/mumble/tests/test_hooks.py b/allianceauth/services/modules/mumble/tests/test_hooks.py new file mode 100644 index 00000000..b619e8aa --- /dev/null +++ b/allianceauth/services/modules/mumble/tests/test_hooks.py @@ -0,0 +1,88 @@ +from allianceauth.services.modules.mumble.auth_hooks import MumbleService +from allianceauth.services.modules.mumble.models import MumbleUser +from allianceauth.services.modules.mumble.tasks import MumbleTasks +from django.test import TestCase, RequestFactory +from django import urls +from django.contrib.auth.models import User, Group, Permission +from django.core.exceptions import ObjectDoesNotExist + +from allianceauth.tests.auth_utils import AuthUtils + +MODULE_PATH = 'allianceauth.services.modules.mumble' +DEFAULT_AUTH_GROUP = 'Member' + + +def add_permissions(): + permission = Permission.objects.get(codename='access_mumble') + members = Group.objects.get_or_create(name=DEFAULT_AUTH_GROUP)[0] + AuthUtils.add_permissions_to_groups([permission], [members]) + + +class MumbleHooksTestCase(TestCase): + def setUp(self): + self.member = 'member_user' + member = AuthUtils.create_member(self.member) + AuthUtils.add_main_character(member, 'auth_member', '12345', corp_id='111', corp_name='Test Corporation', corp_ticker='TESTR') + member = User.objects.get(pk=member.pk) + MumbleUser.objects.create(user=member) + self.none_user = 'none_user' + none_user = AuthUtils.create_user(self.none_user) + self.service = MumbleService + add_permissions() + + def test_has_account(self): + member = User.objects.get(username=self.member) + none_user = User.objects.get(username=self.none_user) + self.assertTrue(MumbleTasks.has_account(member)) + self.assertFalse(MumbleTasks.has_account(none_user)) + + def test_service_enabled(self): + service = self.service() + member = User.objects.get(username=self.member) + none_user = User.objects.get(username=self.none_user) + + self.assertTrue(service.service_active_for_user(member)) + self.assertFalse(service.service_active_for_user(none_user)) + + def test_validate_user(self): + service = self.service() + # Test member is not deleted + member = User.objects.get(username=self.member) + service.validate_user(member) + self.assertTrue(member.mumble) + + # Test none user is deleted + none_user = User.objects.get(username=self.none_user) + MumbleUser.objects.create(user=none_user) + service.validate_user(none_user) + with self.assertRaises(ObjectDoesNotExist): + none_mumble = User.objects.get(username=self.none_user).mumble + + def test_delete_user(self): + member = User.objects.get(username=self.member) + + service = self.service() + result = service.delete_user(member) + + self.assertTrue(result) + with self.assertRaises(ObjectDoesNotExist): + mumble_user = User.objects.get(username=self.member).mumble + + def test_render_services_ctrl(self): + service = self.service() + member = User.objects.get(username=self.member) + request = RequestFactory().get('/services/') + request.user = member + + response = service.render_services_ctrl(request) + self.assertTemplateUsed(service.service_ctrl_template) + self.assertIn(urls.reverse('mumble:deactivate'), response) + self.assertIn(urls.reverse('mumble:reset_password'), response) + self.assertIn(urls.reverse('mumble:set_password'), response) + + # Test register becomes available + member.mumble.delete() + member = User.objects.get(username=self.member) + request.user = member + response = service.render_services_ctrl(request) + self.assertIn(urls.reverse('mumble:activate'), response) diff --git a/allianceauth/services/modules/mumble/tests/test_models.py b/allianceauth/services/modules/mumble/tests/test_models.py new file mode 100644 index 00000000..76139fd7 --- /dev/null +++ b/allianceauth/services/modules/mumble/tests/test_models.py @@ -0,0 +1,208 @@ +import unittest +from django.test import TestCase +from django.utils import timezone +from django.contrib.auth.models import User, Group +from unittest.mock import patch +from datetime import timedelta + +from ..models import ( + MumbleUser, + TempLink, + TempUser, + IdlerHandler, + MumbleServerServer +) + + +class MumbleUserTests(TestCase): + def setUp(self): + """ + Create test data before each test. + """ + # Create a regular Django user + self.user = User.objects.create_user(username='john', password='johnpassword') + # Add a group to the user + self.group = Group.objects.create(name='Test Group') + self.user.groups.add(self.group) + self.user.save() + + # Create a MumbleUser instance + self.mumble_user = MumbleUser.objects.create( + user=self.user, + username='john_mumble', + pwhash='dummyhash' + ) + + def test_mumble_user_str(self): + """ + Test that __str__ returns the username. + """ + self.assertEqual(str(self.mumble_user), 'john_mumble') + + def test_update_password_no_arg(self): + """ + Test update_password when no password is provided + (it should generate a random one). + """ + old_pwhash = self.mumble_user.pwhash + self.mumble_user.update_password() # No password argument + # pwhash should have changed (random pass) + self.assertNotEqual(old_pwhash, self.mumble_user.pwhash) + self.assertTrue(self.mumble_user.credentials) # Should have 'username' & 'password' + + def test_update_password_custom(self): + """ + Test update_password with a custom password. + """ + old_pwhash = self.mumble_user.pwhash + self.mumble_user.update_password(password='myCustomPassword123') + self.assertNotEqual(old_pwhash, self.mumble_user.pwhash) + # After a custom password, credentials shouldn't be updated with 'password' key + self.assertFalse('password' in self.mumble_user.credentials) + + def test_reset_password(self): + """ + reset_password is basically an alias to update_password with no password argument. + """ + old_pwhash = self.mumble_user.pwhash + self.mumble_user.reset_password() + self.assertNotEqual(old_pwhash, self.mumble_user.pwhash) + self.assertTrue(self.mumble_user.credentials) + + def test_group_string(self): + """ + Ensure group_string returns a comma separated list of groups + including the user.profile.state.name (if it exists). + + For simplicity, we mock user.profile.state.name. + """ + with patch('django.contrib.auth.models.User.profile') as mock_profile: + mock_state = unittest.mock.Mock() + mock_state.name = 'Active' + mock_profile.state = mock_state + + group_str = self.mumble_user.group_string() + # We expect something like "Active," + self.assertIn('Active', group_str) + self.assertIn(self.group.name.replace(' ', '-'), group_str) # spaces replaced with '-' + + def test_create_mumble_user_success(self): + """ + Test the create(...) method for MumbleUser. + We patch user.profile to simulate a main_character name. + """ + new_user = User.objects.create_user( + username='jane', + password='janepassword' + ) + with patch('django.contrib.auth.models.User.profile') as mock_profile: + mock_profile.main_character.character_name = 'Jane Main' + # Attempt to create MumbleUser with .create() + result = self.mumble_user.create(new_user) + self.assertIsNot(result, False, "Expected a MumbleUser, not False") + # Check username was sanitized (spaces -> underscores) in get_username + self.assertEqual(result.username, 'Jane_Main') + # credentials should have username + generated password + self.assertIn('username', result.credentials) + self.assertIn('password', result.credentials) + + def test_create_mumble_user_attribute_error(self): + """ + Test the create(...) method’s exception branch + if the user’s profile or main_character is missing. + """ + new_user = User.objects.create_user( + username='jack', + password='jackpassword' + ) + # In this scenario, 'profile' raises an AttributeError + with patch('django.contrib.auth.models.User.profile', side_effect=AttributeError): + result = self.mumble_user.create(new_user) + self.assertFalse(result, "Expected result to be False on error") + + +class TempUserTests(TestCase): + def setUp(self): + """ + Set up data for TempUser tests. + """ + self.temp_link = TempLink.objects.create( + expires=timezone.now() + timedelta(days=1), + link_ref="my123link" + ) + self.temp_user = TempUser.objects.create( + name="GuestName", + username="Guest_123", + pwhash="dummyhash", + expires=timezone.now() + timedelta(days=1), + templink=self.temp_link + ) + + def test_temp_user_str(self): + """ + Verify the string representation for a TempUser. + """ + self.assertIn("Guest_123", str(self.temp_user)) + self.assertIn("GuestName", str(self.temp_user)) + + def test_group_string(self): + """ + Overridden group_string from MumbleUser. Should return ["Guest"]. + """ + group_str = self.temp_user.group_string() + self.assertIn("Guest", group_str) + + +class IdlerHandlerTests(TestCase): + def setUp(self): + self.idler = IdlerHandler.objects.create( + name="MyAFKIdler", + enabled=True, + seconds=7200, + interval=120, + channel=999, + denylist=False, + list="some_list" + ) + + def test_idler_handler_str(self): + self.assertEqual(str(self.idler), "MyAFKIdler") + + +class MumbleServerServerTests(TestCase): + def setUp(self): + self.idler = IdlerHandler.objects.create( + name="MyAFKIdler", + enabled=True, + seconds=3600, + interval=60, + channel=999, + denylist=True, + list="" + ) + self.server = MumbleServerServer.objects.create( + name="MyMumbleServer", + ip="127.0.0.1", + endpoint="127.0.0.1", + port=6502, + secret="supersecret", + watchdog=30, + slice="MumbleServer.ice", + virtual_servers="1,2", + avatar_enable=True, + reject_on_error=True, + offset=1000000000, + idler_handler=self.idler + ) + + def test_mumble_server_str(self): + """ + Test string representation of MumbleServerServer. + """ + self.assertEqual(str(self.server), "MyMumbleServer") + + def test_virtual_servers_list(self): + """ + The virtual_servers_list should parse '1,2' into [1, 2]. + """ + self.assertEqual(self.server.virtual_servers_list(), [1, 2]) diff --git a/allianceauth/services/modules/mumble/tests.py b/allianceauth/services/modules/mumble/tests/test_views.py similarity index 52% rename from allianceauth/services/modules/mumble/tests.py rename to allianceauth/services/modules/mumble/tests/test_views.py index 5c4f3acb..b06044a7 100644 --- a/allianceauth/services/modules/mumble/tests.py +++ b/allianceauth/services/modules/mumble/tests/test_views.py @@ -1,5 +1,8 @@ from unittest import mock +from allianceauth.services.modules.mumble.auth_hooks import MumbleService +from allianceauth.services.modules.mumble.models import MumbleUser +from allianceauth.services.modules.mumble.tasks import MumbleTasks from django.test import TestCase, RequestFactory from django import urls from django.contrib.auth.models import User, Group, Permission @@ -7,90 +10,14 @@ from django.core.exceptions import ObjectDoesNotExist from allianceauth.tests.auth_utils import AuthUtils -from .auth_hooks import MumbleService -from .models import MumbleUser -from .tasks import MumbleTasks - MODULE_PATH = 'allianceauth.services.modules.mumble' DEFAULT_AUTH_GROUP = 'Member' - def add_permissions(): permission = Permission.objects.get(codename='access_mumble') members = Group.objects.get_or_create(name=DEFAULT_AUTH_GROUP)[0] AuthUtils.add_permissions_to_groups([permission], [members]) - -class MumbleHooksTestCase(TestCase): - def setUp(self): - self.member = 'member_user' - member = AuthUtils.create_member(self.member) - AuthUtils.add_main_character(member, 'auth_member', '12345', corp_id='111', corp_name='Test Corporation', corp_ticker='TESTR') - member = User.objects.get(pk=member.pk) - MumbleUser.objects.create(user=member) - self.none_user = 'none_user' - none_user = AuthUtils.create_user(self.none_user) - self.service = MumbleService - add_permissions() - - def test_has_account(self): - member = User.objects.get(username=self.member) - none_user = User.objects.get(username=self.none_user) - self.assertTrue(MumbleTasks.has_account(member)) - self.assertFalse(MumbleTasks.has_account(none_user)) - - def test_service_enabled(self): - service = self.service() - member = User.objects.get(username=self.member) - none_user = User.objects.get(username=self.none_user) - - self.assertTrue(service.service_active_for_user(member)) - self.assertFalse(service.service_active_for_user(none_user)) - - def test_validate_user(self): - service = self.service() - # Test member is not deleted - member = User.objects.get(username=self.member) - service.validate_user(member) - self.assertTrue(member.mumble) - - # Test none user is deleted - none_user = User.objects.get(username=self.none_user) - MumbleUser.objects.create(user=none_user) - service.validate_user(none_user) - with self.assertRaises(ObjectDoesNotExist): - none_mumble = User.objects.get(username=self.none_user).mumble - - def test_delete_user(self): - member = User.objects.get(username=self.member) - - service = self.service() - result = service.delete_user(member) - - self.assertTrue(result) - with self.assertRaises(ObjectDoesNotExist): - mumble_user = User.objects.get(username=self.member).mumble - - def test_render_services_ctrl(self): - service = self.service() - member = User.objects.get(username=self.member) - request = RequestFactory().get('/services/') - request.user = member - - response = service.render_services_ctrl(request) - self.assertTemplateUsed(service.service_ctrl_template) - self.assertIn(urls.reverse('mumble:deactivate'), response) - self.assertIn(urls.reverse('mumble:reset_password'), response) - self.assertIn(urls.reverse('mumble:set_password'), response) - - # Test register becomes available - member.mumble.delete() - member = User.objects.get(username=self.member) - request.user = member - response = service.render_services_ctrl(request) - self.assertIn(urls.reverse('mumble:activate'), response) - - class MumbleViewsTestCase(TestCase): def setUp(self): self.member = AuthUtils.create_member('auth_member') @@ -113,7 +40,6 @@ class MumbleViewsTestCase(TestCase): # create mumble_user = MumbleUser.objects.get(user=self.member) self.assertEqual(mumble_user.username, expected_username) - self.assertTrue(MumbleUser.objects.user_exists(expected_username)) self.assertEqual(str(mumble_user), expected_username) self.assertEqual(mumble_user.display_name, expected_displayname) self.assertTrue(mumble_user.pwhash) @@ -128,7 +54,6 @@ class MumbleViewsTestCase(TestCase): mumble_user = MumbleUser.objects.get(user=self.member) expected_displayname = '[TESTU]auth_member_updated' self.assertEqual(mumble_user.username, expected_username) - self.assertTrue(MumbleUser.objects.user_exists(expected_username)) self.assertEqual(str(mumble_user), expected_username) self.assertEqual(mumble_user.display_name, expected_displayname) self.assertTrue(mumble_user.pwhash) @@ -167,20 +92,3 @@ class MumbleViewsTestCase(TestCase): self.assertNotEqual(MumbleUser.objects.get(user=self.member).pwhash, old_pwd) self.assertTemplateUsed(response, 'services/service_credentials.html') self.assertContains(response, 'auth_member') - -class MumbleManagerTestCase(TestCase): - def setUp(self): - from .models import MumbleManager - self.manager = MumbleManager - - def test_generate_random_password(self): - password = self.manager.generate_random_pass() - - self.assertEqual(len(password), 16) - self.assertIsInstance(password, str) - - def test_gen_pwhash(self): - pwhash = self.manager.gen_pwhash('test') - - self.assertEqual(pwhash[:15], '$bcrypt-sha256$') - self.assertEqual(len(pwhash), 83)