Skip to content
Open
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
16 changes: 12 additions & 4 deletions api/features/multivariate/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,21 @@ def validate_key(self, value: str | None) -> str | None:

def validate(self, attrs): # type: ignore[no-untyped-def]
attrs = super().validate(attrs)
feature = attrs["feature"]
default_percentage_allocation = attrs["default_percentage_allocation"]

# Safely get feature and allocation, falling back to instance for PATCH requests
feature = attrs.get("feature", getattr(self.instance, "feature", None))
default_percentage_allocation = attrs.get(
"default_percentage_allocation",
getattr(self.instance, "default_percentage_allocation", 0),
)

total_sibling_percentage_allocation = (
self._get_siblings(feature).aggregate(
total_percentage_allocation=Sum("default_percentage_allocation")
)["total_percentage_allocation"]
or 0
)

total_percentage_allocation = (
total_sibling_percentage_allocation + default_percentage_allocation
)
Expand Down Expand Up @@ -136,10 +142,12 @@ def _validate_environment_allocations(
)

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

feature = attrs.get("feature", 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."
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import json
import uuid

import pytest
Expand Down Expand Up @@ -105,3 +106,33 @@ def test_list_mv_options__feature_in_other_project__returns_404(

# Then
assert response.status_code == status.HTTP_404_NOT_FOUND


def test_partial_update_multivariate_option__valid_data__returns_200_and_updates(
admin_client: APIClient,
project: Project,
multivariate_feature: Feature,
) -> None:
# Given
mv_option = multivariate_feature.multivariate_options.first()

assert mv_option is not None

url = f"/api/v1/projects/{project.id}/features/{multivariate_feature.id}/mv-options/{mv_option.id}/"

new_key = "hero"
data = {"key": new_key}

initial_allocation = mv_option.default_percentage_allocation

# When
response = admin_client.patch(
url, data=json.dumps(data), content_type="application/json"
)

# Then
assert response.status_code == status.HTTP_200_OK

mv_option.refresh_from_db()
assert mv_option.key == new_key
assert mv_option.default_percentage_allocation == initial_allocation
Loading