content: from django.test import TestCase
  from django.test import override_settings
  
  from circuits.api.serializers import ProviderSerializer
  from circuits.forms import ProviderForm
  from circuits.models import Provider
  from ipam.models import ASN, RIR
  from netbox.choices import CSVDelimiterChoices, ImportFormatChoices
  from utilities.testing import APITestCase, ModelViewTestCase, create_tags, post_data
  
  
  class ModelFormCustomValidationTest(TestCase):
  
      @override_settings(CUSTOM_VALIDATORS={
          'circuits.provider': [
              {'tags': {'required': True}}
          ]
      })
      def test_tags_validation(self):
          """
          Check that custom validation rules work for tag assignment.
          """
          data = {
              'name': 'Provider 1',
              'slug': 'provider-1',
          }
          form = ProviderForm(data)
          self.assertFalse(form.is_valid())
  
          tags = create_tags('Tag1', 'Tag2', 'Tag3')
          data['tags'] = [tag.pk for tag in tags]
          form = ProviderForm(data)
          self.assertTrue(form.is_valid())
  
      @override_settings(CUSTOM_VALIDATORS={
          'circuits.provider': [
              {'asns': {'required': True}}
          ]
      })
      def test_m2m_validation(self):
          """
          Check that custom validation rules work for many-to-many fields.
          """
          data = {
              'name': 'Provider 1',
              'slug': 'provider-1',
          }
          form = ProviderForm(data)
          self.assertFalse(form.is_valid())
  
          rir = RIR.objects.create(name='RIR 1', slug='rir-1')
          asns = ASN.objects.bulk_create((
              ASN(rir=rir, asn=65001),
              ASN(rir=rir, asn=65002),
              ASN(rir=rir, asn=65003),
          ))
          data['asns'] = [asn.pk for asn in asns]
          form = ProviderForm(data)
          self.assertTrue(form.is_valid())
  
  
  class BulkEditCustomValidationTest(ModelViewTestCase):
      model = Provider
  
      @classmethod
      def setUpTestData(cls):
          rir = RIR.objects.create(name='RIR 1', slug='rir-1')
          asns = ASN.objects.bulk_create((
              ASN(rir=rir, asn=65001),
              ASN(rir=rir, asn=65002),
              ASN(rir=rir, asn=65003),
          ))
  
          providers = (
              Provider(name='Provider 1', slug='provider-1'),
              Provider(name='Provider 2', slug='provider-2'),
              Provider(name='Provider 3', slug='provider-3'),
          )
          Provider.objects.bulk_create(providers)
          for provider in providers:
              provider.asns.set(asns)
  
      @override_settings(CUSTOM_VALIDATORS={
          'circuits.provider': [
              {'asns': {'required': True}}
          ]
      })
      def test_bulk_edit_without_m2m(self):
          """
          Check that custom validation rules do not interfere with bulk editing.
          """
          data = {
              'pk': list(Provider.objects.values_list('pk', flat=True)),
              '_apply': '',
              'description': 'New description',
          }
          self.add_permissions(
              'circuits.view_provider',
              'circuits.change_provider',
          )
  
          # Bulk edit the description without changing ASN assignments
          request = {
              'path': self._get_url('bulk_edit'),
              'data': post_data(data),
          }
          response = self.client.post(**request)
          self.assertHttpStatus(response, 302)
          self.assertEqual(
              Provider.objects.filter(description=data['description']).count(),
              len(data['pk'])
          )
  
      @override_settings(CUSTOM_VALIDATORS={
          'circuits.provider': [
              {'asns': {'required': True}}
          ]
      })
      def test_bulk_edit_m2m(self):
          """
          Test that custom validation rules are enforced during bulk editing.
          """
          data = {
              'pk': list(Provider.objects.values_list('pk', flat=True)),
              '_apply': '',
              'description': 'New description',
          }
          self.add_permissions(
              'circuits.view_provider',
              'circuits.change_provider',
              'ipam.view_asn',
          )
  
          # Change the ASN assignments
          asn = ASN.objects.first()
          data['asns'] = [asn.pk]
          request = {
              'path': self._get_url('bulk_edit'),
              'data': post_data(data),
          }
          response = self.client.post(**request)
          self.assertHttpStatus(response, 302)
          for provider in Provider.objects.all():
              self.assertEqual(len(provider.asns.all()), 1)
  
          # Attempt to remove the ASN assignments
          data.pop('asns')
          data['_nullify'] = 'asns'
          request = {
              'path': self._get_url('bulk_edit'),
              'data': post_data(data),
          }
          response = self.client.post(**request)
          self.assertHttpStatus(response, 200)
          for provider in Provider.objects.all():
              self.assertTrue(provider.asns.exists())
  
  
  class BulkImportCustomValidationTest(ModelViewTestCase):
      model = Provider
  
      @classmethod
      def setUpTestData(cls):
          create_tags('Tag1', 'Tag2', 'Tag3')
  
      @override_settings(CUSTOM_VALIDATORS={
          'circuits.provider': [
              {'tags': {'required': True}}
          ]
      })
      def test_bulk_import_invalid(self):
          """
          Test that custom validation rules are enforced during bulk import.
          """
          csv_data = (
              "name,slug",
              "Provider 1,provider-1",
              "Provider 2,provider-2",
              "Provider 3,provider-3",
          )
          data = {
              'data': '\n'.join(csv_data),
              'format': ImportFormatChoices.CSV,
              'csv_delimiter': CSVDelimiterChoices.COMMA,
          }
          self.add_permissions(
              'circuits.view_provider',
              'circuits.add_provider',
              'extras.view_tag',
          )
  
          # Attempt to import providers without tags
          request = {
              'path': self._get_url('bulk_import'),
              'data': post_data(data),
          }
          response = self.client.post(**request)
          self.assertHttpStatus(response, 200)
          self.assertFalse(Provider.objects.exists())
  
          # Import providers successfully with tag assignments
          csv_data = (
              "name,slug,tags",
              "Provider 1,provider-1,tag1",
              "Provider 2,provider-2,tag2",
              "Provider 3,provider-3,tag3",
          )
          data['data'] = '\n'.join(csv_data)
          request = {
              'path': self._get_url('bulk_import'),
              'data': post_data(data),
          }
          response = self.client.post(**request)
          self.assertHttpStatus(response, 302)
          self.assertTrue(Provider.objects.exists())
  
  
  class APISerializerCustomValidationTest(APITestCase):
  
      @override_settings(CUSTOM_VALIDATORS={
          'circuits.provider': [
              {'tags': {'required': True}}
          ]
      })
      def test_tags_validation(self):
          """
          Check that custom validation rules work for tag assignment.
          """
          data = {
              'name': 'Provider 1',
              'slug': 'provider-1',
          }
          serializer = ProviderSerializer(data=data)
          self.assertFalse(serializer.is_valid())
  
          tags = create_tags('Tag1', 'Tag2', 'Tag3')
          data['tags'] = [tag.pk for tag in tags]
          serializer = ProviderSerializer(data=data)
          self.assertTrue(serializer.is_valid())
  
      @override_settings(CUSTOM_VALIDATORS={
          'circuits.provider': [
              {'asns': {'required': True}}
          ]
      })
      def test_m2m_validation(self):
          """
          Check that custom validation rules work for many-to-many fields.
          """
          data = {
              'name': 'Provider 1',
              'slug': 'provider-1',
          }
          serializer = ProviderSerializer(data=data)
          self.assertFalse(serializer.is_valid())
  
          rir = RIR.objects.create(name='RIR 1', slug='rir-1')
          asns = ASN.objects.bulk_create((
              ASN(rir=rir, asn=65001),
              ASN(rir=rir, asn=65002),
              ASN(rir=rir, asn=65003),
          ))
          data['asns'] = [asn.pk for asn in asns]
          serializer = ProviderSerializer(data=data)
          self.assertTrue(serializer.is_valid())
  