Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions tests/test_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import pytest
from django import VERSION as django_version
from django.core.exceptions import ValidationError as DjangoValidationError
from django.db import DataError, models
from django.test import TestCase

Expand Down Expand Up @@ -779,6 +780,75 @@ class Meta:
assert serializer.is_valid()


class UniqueConstraintWithRelationModel(models.Model):
value = models.IntegerField()
first_related = models.ForeignKey(IntegerFieldModel, related_name='+', on_delete=models.CASCADE, null=True, blank=True)
second_related = models.ForeignKey(IntegerFieldModel, related_name='+', on_delete=models.CASCADE, null=True, blank=True)

class Meta:
constraints = [
models.UniqueConstraint(fields=('value', 'first_related'), condition=models.Q(second_related__isnull=True), name='unique_constraint_with_relationa'),
Copy link

Copilot AI Dec 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The constraint name 'unique_constraint_with_relationa' appears to be truncated or missing an underscore. Based on Django naming conventions and the pattern in line 791 ('unique_constraint_with_relationb'), this should likely be 'unique_constraint_with_relation_a' or extend to something more descriptive like 'unique_constraint_with_relation_first'.

Copilot uses AI. Check for mistakes.
models.UniqueConstraint(fields=('value', 'second_related'), condition=models.Q(first_related__isnull=True), name='unique_constraint_with_relationb'),
Copy link

Copilot AI Dec 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The constraint name 'unique_constraint_with_relationb' appears to be truncated or missing an underscore. For consistency with Django naming conventions, this should likely be 'unique_constraint_with_relation_b' or extend to something more descriptive like 'unique_constraint_with_relation_second'.

Copilot uses AI. Check for mistakes.
]


class UniqueConstraintWithRelationModelSerializer(serializers.ModelSerializer):
class Meta:
model = UniqueConstraintWithRelationModel
fields = serializers.ALL_FIELDS
Copy link

Copilot AI Dec 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fields specification uses 'serializers.ALL_FIELDS' which is inconsistent with the rest of the test file. All other ModelSerializer definitions in this file use the string literal 'all' (see lines 32, 62, 177, 183, 623, 863, 933, 972). For consistency, this should be changed to 'all'.

Suggested change
fields = serializers.ALL_FIELDS
fields = '__all__'

Copilot uses AI. Check for mistakes.


class TestUniqueConstraintWithRelationValidation(TestCase):
def setUp(self):
self.related_model = IntegerFieldModel.objects.create(integer=1)
self.instance_first = UniqueConstraintWithRelationModel.objects.create(
value=1,
first_related=self.related_model,
second_related=None
)
self.instance_second = UniqueConstraintWithRelationModel.objects.create(
value=1,
first_related=None,
second_related=self.related_model
)

def test_unique_constraint_with_relation_first(self):
instance = UniqueConstraintWithRelationModel(value=1, first_related=self.related_model, second_related=None)
with pytest.raises(DjangoValidationError) as excinfo:
instance.validate_constraints()

assert str(excinfo.value) == "{'__all__': ['Constraint “unique_constraint_with_relationa” is violated.']}"
serializer = UniqueConstraintWithRelationModelSerializer(data={
'value': 1,
'first_related': self.related_model.pk,
'second_related': None
})
assert not serializer.is_valid()
assert serializer.errors == {
'non_field_errors': [
'The fields value, first_related must make a unique set.'
]
}

def test_unique_constraint_with_relation_second(self):
instance = UniqueConstraintWithRelationModel(value=1, second_related=self.related_model, first_related=None)
with pytest.raises(DjangoValidationError) as excinfo:
instance.validate_constraints()

assert str(excinfo.value) == "{'__all__': ['Constraint “unique_constraint_with_relationb” is violated.']}"
serializer = UniqueConstraintWithRelationModelSerializer(data={
'value': 1,
'first_related': None,
'second_related': self.related_model.pk
})
assert not serializer.is_valid()
assert serializer.errors == {
'non_field_errors': [
'The fields value, second_related must make a unique set.'
]
}
Comment on lines +801 to +849
Copy link

Copilot AI Dec 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test suite is missing a positive test case to verify that the unique constraint validation passes when the constraint conditions are not violated. Consider adding a test to verify that creating a new instance with different values (e.g., value=2) or when the condition doesn't apply (e.g., both first_related and second_related are set) is allowed and passes validation.

Copilot uses AI. Check for mistakes.
Comment on lines +801 to +849
Copy link

Copilot AI Dec 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test suite is missing a test case for updating an existing instance. Following the pattern established in other validator tests (e.g., test_updated_instance_excluded_from_unique_together at line 239), there should be a test to verify that when updating an instance with the same values, it doesn't fail validation against itself.

Copilot uses AI. Check for mistakes.
Comment on lines +801 to +849
Copy link

Copilot AI Dec 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test should also verify the case where both first_related and second_related are non-null. Based on the constraint conditions (second_related__isnull=True and first_related__isnull=True), when both fields have values, neither constraint should apply and the validation should pass. This is an important edge case that demonstrates the constraint conditions are being properly evaluated.

Copilot uses AI. Check for mistakes.


# Tests for `UniqueForDateValidator`
# ----------------------------------

Expand Down
Loading