feat: add bulk images and tenant autofill
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
from io import BytesIO
|
||||
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.test import SimpleTestCase
|
||||
from django.utils.datastructures import MultiValueDict
|
||||
from PIL import Image
|
||||
|
||||
from netbox_utilities.forms import BulkImageUploadForm
|
||||
|
||||
|
||||
class BulkImageUploadFormTest(SimpleTestCase):
|
||||
@staticmethod
|
||||
def _image(name):
|
||||
content = BytesIO()
|
||||
Image.new("RGB", (2, 2), "white").save(content, format="PNG")
|
||||
return SimpleUploadedFile(name, content.getvalue(), content_type="image/png")
|
||||
|
||||
def test_accepts_multiple_images(self):
|
||||
files = MultiValueDict({"images": [self._image("front.png"), self._image("rear.png")]})
|
||||
|
||||
form = BulkImageUploadForm(data={"description": "Dokumentation"}, files=files)
|
||||
|
||||
self.assertTrue(form.is_valid(), form.errors)
|
||||
self.assertEqual(len(form.cleaned_data["images"]), 2)
|
||||
self.assertEqual(form.cleaned_data["description"], "Dokumentation")
|
||||
|
||||
def test_requires_at_least_one_image(self):
|
||||
form = BulkImageUploadForm(data={}, files={})
|
||||
|
||||
self.assertFalse(form.is_valid())
|
||||
self.assertIn("images", form.errors)
|
||||
@@ -0,0 +1,25 @@
|
||||
from types import SimpleNamespace
|
||||
|
||||
from django.test import RequestFactory, SimpleTestCase
|
||||
|
||||
from netbox_utilities.views import BulkImageUploadView
|
||||
|
||||
|
||||
class BulkImageUploadViewTest(SimpleTestCase):
|
||||
def setUp(self):
|
||||
self.factory = RequestFactory()
|
||||
self.parent = SimpleNamespace(get_absolute_url=lambda: "/dcim/sites/42/")
|
||||
|
||||
def test_accepts_local_return_url(self):
|
||||
request = self.factory.get("/plugins/utilities/images/bulk-upload/?return_url=/dcim/sites/42/images/")
|
||||
|
||||
result = BulkImageUploadView()._return_url(request, self.parent)
|
||||
|
||||
self.assertEqual(result, "/dcim/sites/42/images/")
|
||||
|
||||
def test_rejects_external_return_url(self):
|
||||
request = self.factory.get("/plugins/utilities/images/bulk-upload/?return_url=https://example.net/steal")
|
||||
|
||||
result = BulkImageUploadView()._return_url(request, self.parent)
|
||||
|
||||
self.assertEqual(result, "/dcim/sites/42/")
|
||||
@@ -0,0 +1,84 @@
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import patch
|
||||
|
||||
from django import forms
|
||||
from django.test import SimpleTestCase
|
||||
from tenancy.models import TenantGroup
|
||||
|
||||
from netbox_utilities.tenant_autofill import apply_tenant_autofill, infer_tenant_id, tenant_id_from_object
|
||||
from netbox_utilities.tenant_scope import ActiveTenantScope, active_tenant_scope
|
||||
|
||||
|
||||
class FakeMeta:
|
||||
def __init__(self, *field_names):
|
||||
self.field_names = field_names
|
||||
|
||||
def get_fields(self):
|
||||
return [SimpleNamespace(name=name) for name in self.field_names]
|
||||
|
||||
|
||||
class FakeObject:
|
||||
def __init__(self, *, tenant_id=None, **relations):
|
||||
self.tenant_id = tenant_id
|
||||
self._meta = FakeMeta("tenant", *relations)
|
||||
for name, value in relations.items():
|
||||
setattr(self, name, value)
|
||||
|
||||
|
||||
class FakeQuerySet:
|
||||
def __init__(self, model):
|
||||
self.model = model
|
||||
|
||||
|
||||
class TenantAutofillTest(SimpleTestCase):
|
||||
def test_finds_tenant_through_parent_relation(self):
|
||||
rack = FakeObject(tenant_id=42)
|
||||
device = FakeObject(rack=rack)
|
||||
|
||||
self.assertEqual(tenant_id_from_object(device), 42)
|
||||
|
||||
def test_uses_selected_global_tenant_as_fallback(self):
|
||||
form = SimpleNamespace(
|
||||
fields={"tenant": forms.IntegerField()},
|
||||
initial={},
|
||||
instance=FakeObject(),
|
||||
is_bound=False,
|
||||
)
|
||||
token = active_tenant_scope.set(ActiveTenantScope("tenant", 17, frozenset({17})))
|
||||
try:
|
||||
self.assertEqual(infer_tenant_id(form), 17)
|
||||
finally:
|
||||
active_tenant_scope.reset(token)
|
||||
|
||||
@patch("netbox_utilities.tenant_autofill._infer_group_id", return_value=None)
|
||||
@patch("netbox_utilities.tenant_autofill.infer_tenant_id", return_value=23)
|
||||
def test_prefills_and_marks_tenant_field(self, _infer_tenant_id, _infer_group_id):
|
||||
tenant_field = forms.IntegerField()
|
||||
form = SimpleNamespace(
|
||||
fields={"tenant": tenant_field},
|
||||
initial={},
|
||||
instance=FakeObject(),
|
||||
is_bound=False,
|
||||
)
|
||||
|
||||
apply_tenant_autofill(form)
|
||||
|
||||
self.assertEqual(form.initial["tenant"], 23)
|
||||
self.assertEqual(tenant_field.widget.attrs["data-netbox-utilities-autofilled-tenant"], "23")
|
||||
|
||||
@patch("netbox_utilities.tenant_autofill._infer_group_id", return_value=9)
|
||||
def test_prefills_tenant_group_relation(self, _infer_group_id):
|
||||
group_field = SimpleNamespace(
|
||||
queryset=FakeQuerySet(TenantGroup),
|
||||
help_text="",
|
||||
)
|
||||
form = SimpleNamespace(
|
||||
fields={"group": group_field},
|
||||
initial={},
|
||||
instance=SimpleNamespace(group_id=None),
|
||||
is_bound=False,
|
||||
)
|
||||
|
||||
apply_tenant_autofill(form)
|
||||
|
||||
self.assertEqual(form.initial["group"], 9)
|
||||
Reference in New Issue
Block a user