1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-09 19:56:48 +00:00

test: each app keeps its tests in a tests package

131 test modules sat next to the code they test; instances alone had
51 of them beside views.py and utils.py. They move into a
tests/ package per app, and the JavaScript checks into
webvirtcloud/tests/js. Each non-empty tests.py becomes tests/test_views.py;
the empty generated stubs are removed.

Imports of the app's own modules become absolute, paths built from
__file__ go one level up, the live helper is instances.tests.livetest,
and coverage omits */tests/*. The suite discovers the same 960 tests as
before.
This commit is contained in:
catborise 2026-10-12 10:37:29 +03:00
parent 0906838193
commit c55f52f025
154 changed files with 27 additions and 39 deletions

0
admin/tests/__init__.py Normal file
View file

View file

@ -0,0 +1,56 @@
"""Superusers list the ownership kept for VMs that vanished and can remove it."""
from datetime import timedelta
from django.contrib.auth.models import User
from django.test import TestCase, override_settings
from django.urls import reverse
from django.utils import timezone
from instances.models import InstanceTombstone
UUID = "00000000-0000-4000-8000-000000000001"
class TombstoneTests(TestCase):
def setUp(self):
self.client.force_login(User.objects.create_superuser("ts-admin", "ts@example.com", "pw"))
self.owner = User.objects.create_user("ts-owner", password="pw")
self.tombstone = InstanceTombstone.objects.create(
uuid=UUID,
name="ts-vm",
owners=[
{"user": self.owner.id, "is_change": True, "is_delete": False, "is_vnc": True},
{"user": 999999, "is_change": False, "is_delete": False, "is_vnc": False},
],
)
@override_settings(INSTANCE_OWNERSHIP_RETENTION_DAYS=7)
def test_the_list_shows_the_vm_its_owners_and_when_it_expires(self):
removed = timezone.now() - timedelta(days=2)
InstanceTombstone.objects.filter(pk=self.tombstone.pk).update(removed=removed)
response = self.client.get(reverse("admin:tombstone_list"))
self.assertEqual(response.status_code, 200)
row = response.context["tombstones"][0]
self.assertEqual(row.owner_names, ["ts-owner", "deleted user"])
self.assertEqual(row.expires, removed + timedelta(days=7))
self.assertContains(response, "ts-vm")
self.assertContains(response, UUID)
self.assertContains(response, "ts-owner")
def test_only_superusers_see_or_remove_them(self):
self.client.force_login(self.owner)
self.assertEqual(self.client.get(reverse("admin:tombstone_list")).status_code, 403)
url = reverse("admin:tombstone_delete", args=[self.tombstone.pk])
self.assertEqual(self.client.post(url).status_code, 403)
self.assertTrue(InstanceTombstone.objects.exists())
def test_a_get_only_asks_for_confirmation(self):
response = self.client.get(reverse("admin:tombstone_delete", args=[self.tombstone.pk]))
self.assertContains(response, "ts-vm")
self.assertTrue(InstanceTombstone.objects.exists())
def test_a_post_removes_it(self):
response = self.client.post(reverse("admin:tombstone_delete", args=[self.tombstone.pk]))
self.assertRedirects(response, reverse("admin:tombstone_list"))
self.assertFalse(InstanceTombstone.objects.exists())

View file

@ -0,0 +1,65 @@
"""Creating a user in the admin pages: the password reaches the database only
hashed, and the configured password validators apply as on the change forms."""
from django.contrib.auth.models import Group, Permission, User
from django.db import connection
from django.test import TestCase, override_settings
from django.urls import reverse
RAW = "Raw-Passw0rd-in-the-form"
LIMITS = {"max_instances": 1, "max_cpus": 1, "max_memory": 1024, "max_disk_size": 4}
class UserCreateTests(TestCase):
def setUp(self):
self.client.force_login(User.objects.create_superuser("uc-admin", "uc@example.com", "pw"))
self.change_password = Permission.objects.get(content_type__app_label="accounts", codename="change_password")
def create(self, **data):
return self.client.post(reverse("admin:user_create"), {"username": "newbie", "password": RAW, **LIMITS, **data})
def test_the_raw_password_is_never_written(self):
written = []
def record(execute, sql, params, many, context):
if RAW in repr(params):
written.append(sql)
return execute(sql, params, many, context)
with connection.execute_wrapper(record):
response = self.create()
self.assertRedirects(response, reverse("admin:user_list"))
self.assertEqual(written, [])
self.assertTrue(User.objects.get(username="newbie").check_password(RAW))
def test_groups_and_permissions_are_saved(self):
group = Group.objects.create(name="uc-group")
self.create(groups=[group.pk], user_permissions=[self.change_password.pk])
user = User.objects.get(username="newbie")
self.assertEqual(list(user.groups.all()), [group])
self.assertEqual(list(user.user_permissions.all()), [self.change_password])
def test_an_unticked_permission_stays_off(self):
self.create()
self.assertFalse(User.objects.get(username="newbie").user_permissions.exists())
@override_settings(
AUTH_PASSWORD_VALIDATORS=[
{"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", "OPTIONS": {"min_length": 30}}
]
)
def test_configured_password_validators_apply(self):
response = self.create()
self.assertEqual(response.status_code, 200)
self.assertContains(response, "at least 30 characters")
self.assertFalse(User.objects.filter(username="newbie").exists())
@override_settings(
AUTH_PASSWORD_VALIDATORS=[{"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator"}]
)
def test_the_password_is_checked_against_the_new_username(self):
response = self.client.post(
reverse("admin:user_create"), {"username": "rumpelstiltskin", "password": "rumpelstiltskin1", **LIMITS}
)
self.assertEqual(response.status_code, 200)
self.assertContains(response, "too similar to the username")

View file

@ -0,0 +1,26 @@
"""After saving a user, the edit page goes back to ?next= only on this site."""
from django.contrib.auth.models import User
from django.test import TestCase
from django.urls import reverse
LIMITS = {"max_instances": 1, "max_cpus": 1, "max_memory": 1024, "max_disk_size": 4}
class UserUpdateNextTests(TestCase):
def setUp(self):
self.client.force_login(User.objects.create_superuser("un-admin", "un@example.com", "pw"))
self.user = User.objects.create_user("un-user", password="pw")
def save(self, next_url):
url = reverse("admin:user_update", args=[self.user.id]) + "?next=" + next_url
return self.client.post(url, {"username": "un-user", "is_active": "on", **LIMITS})
def test_a_page_of_this_site(self):
account = reverse("accounts:account", args=[self.user.id])
self.assertRedirects(self.save(account), account, fetch_redirect_response=False)
def test_another_site_is_not_followed(self):
for next_url in ("https://evil.example/", "//evil.example/", "/\\evil.example/"):
with self.subTest(next_url=next_url):
self.assertRedirects(self.save(next_url), reverse("admin:user_list"), fetch_redirect_response=False)

134
admin/tests/test_views.py Normal file
View file

@ -0,0 +1,134 @@
from django.contrib.auth.models import Group, User
from django.core.exceptions import ObjectDoesNotExist
from django.shortcuts import reverse
from django.test import RequestFactory, TestCase
from accounts.models import UserAttributes
class AdminTestCase(TestCase):
def setUp(self):
self.client.login(request=RequestFactory().get("/"), username="admin", password="admin")
def test_group_list(self):
response = self.client.get(reverse("admin:group_list"))
self.assertEqual(response.status_code, 200)
def test_groups(self):
response = self.client.get(reverse("admin:group_create"))
self.assertEqual(response.status_code, 200)
response = self.client.post(
reverse("admin:group_create"), {"name": "Test Group"}
)
self.assertRedirects(response, reverse("admin:group_list"))
group = Group.objects.get(name="Test Group")
group_id = group.id
response = self.client.get(reverse("admin:group_update", args=[group_id]))
self.assertEqual(response.status_code, 200)
response = self.client.post(
reverse("admin:group_update", args=[group_id]), {"name": "Updated Group Test"}
)
self.assertRedirects(response, reverse("admin:group_list"))
group = Group.objects.get(id=group_id)
self.assertEqual(group.name, "Updated Group Test")
response = self.client.get(reverse("admin:group_delete", args=[group_id]))
self.assertEqual(response.status_code, 200)
response = self.client.post(reverse("admin:group_delete", args=[group_id]))
self.assertRedirects(response, reverse("admin:group_list"))
with self.assertRaises(ObjectDoesNotExist):
Group.objects.get(id=group_id)
def test_user_list(self):
response = self.client.get(reverse("admin:user_list"))
self.assertEqual(response.status_code, 200)
def test_users(self):
response = self.client.get(reverse("admin:user_create"))
self.assertEqual(response.status_code, 200)
response = self.client.post(
reverse("admin:user_create"),
{
"username": "test",
"password": "test",
"max_instances": 1,
"max_cpus": 1,
"max_memory": 1024,
"max_disk_size": 4,
},
)
self.assertRedirects(response, reverse("admin:user_list"))
user = User.objects.get(username="test")
user_id = user.id
ua: UserAttributes = UserAttributes.objects.get(user_id=user_id)
self.assertEqual(ua.user_id, user_id)
self.assertEqual(ua.max_instances, 1)
self.assertEqual(ua.max_cpus, 1)
self.assertEqual(ua.max_memory, 1024)
self.assertEqual(ua.max_disk_size, 4)
response = self.client.get(reverse("admin:user_update", args=[user_id]))
self.assertEqual(response.status_code, 200)
response = self.client.post(
reverse("admin:user_update", args=[user_id]),
{
"username": "utest",
"max_instances": 2,
"max_cpus": 2,
"max_memory": 2048,
"max_disk_size": 8,
},
)
self.assertRedirects(response, reverse("admin:user_list"))
user = User.objects.get(id=user_id)
self.assertEqual(user.username, "utest")
ua = UserAttributes.objects.get(user_id=user_id)
self.assertEqual(ua.user_id, user_id)
self.assertEqual(ua.max_instances, 2)
self.assertEqual(ua.max_cpus, 2)
self.assertEqual(ua.max_memory, 2048)
self.assertEqual(ua.max_disk_size, 8)
# Blocking changes state, so a GET (e.g. an <img> tag) must not do it.
User.objects.filter(id=user_id).update(is_active=True)
response = self.client.get(reverse("admin:user_block", args=[user_id]))
self.assertEqual(response.status_code, 405)
self.assertTrue(User.objects.get(id=user_id).is_active)
response = self.client.post(reverse("admin:user_block", args=[user_id]))
user = User.objects.get(id=user_id)
self.assertFalse(user.is_active)
response = self.client.get(reverse("admin:user_unblock", args=[user_id]))
self.assertEqual(response.status_code, 405)
self.assertFalse(User.objects.get(id=user_id).is_active)
response = self.client.post(reverse("admin:user_unblock", args=[user_id]))
user = User.objects.get(id=user_id)
self.assertTrue(user.is_active)
response = self.client.get(reverse("admin:user_delete", args=[user_id]))
self.assertEqual(response.status_code, 200)
response = self.client.post(reverse("admin:user_delete", args=[user_id]))
self.assertRedirects(response, reverse("admin:user_list"))
with self.assertRaises(ObjectDoesNotExist):
User.objects.get(id=user_id)
def test_logs(self):
response = self.client.get(reverse("admin:logs"))
self.assertEqual(response.status_code, 200)