Skip to content
Closed
Show file tree
Hide file tree
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
9 changes: 6 additions & 3 deletions api/features/multivariate/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def validate_key(self, value: str | None) -> str | None:
raise serializers.ValidationError(RESERVED_VARIANT_KEY_MESSAGE)
return value

def validate(self, attrs): # type: ignore[no-untyped-def]
def validate(self, attrs): # type: ignore[no-untyped-def]
attrs = super().validate(attrs)
feature = attrs["feature"]
default_percentage_allocation = attrs["default_percentage_allocation"]
Expand Down Expand Up @@ -136,16 +136,19 @@ def _validate_environment_allocations(
)

def _validate_key_is_unique(self, attrs: dict[str, typing.Any]) -> None:
key = attrs.get("key") or getattr(self.instance, "key", None)
key = attrs.get("key")
if key is None:
return
if self._get_siblings(attrs["feature"]).filter(key=key).exists():

feature = attrs.get("feature") or getattr(self.instance, "feature", None)

if self._get_siblings(feature).filter(key=key).exists():
raise ValidationError(
{
"key": "Multivariate option with this key already exists for the feature."
}
)

def _get_siblings(self, feature: Feature): # type: ignore[no-untyped-def]
siblings = feature.multivariate_options.all()
if self.instance:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,25 @@ def test_list_mv_options__feature_in_other_project__returns_404(

# Then
assert response.status_code == status.HTTP_404_NOT_FOUND


def test_multivariate_feature_option_create_omitted_allocation_fails_if_siblings_exist(
feature,
):
# Given an existing option taking up 50%
MultivariateFeatureOption.objects.create(
feature=feature,
default_percentage_allocation=50,
type="unicode",
string_value="control",
)

# When we try to create a new one without specifying an allocation
# (Serializer defaults to 100, so 50 + 100 = 150 > 100)
serializer = MultivariateFeatureOptionSerializer(
data={"feature": feature.id, "type": "unicode", "string_value": "variant"}
)

# Then it should fail validation
assert serializer.is_valid() is False
assert "default_percentage_allocation" in serializer.errors
Loading