Skip to content
Draft
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
4 changes: 2 additions & 2 deletions src/sentry/api/serializers/rest_framework/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@


class EmptyListField(ListField):
def to_internal_value(self, data: Any) -> Any:
def to_internal_value(self, data: Any) -> list[Any]:
if data == "":
return ""
return []
return super().to_internal_value(data)
39 changes: 39 additions & 0 deletions tests/sentry/api/serializers/rest_framework/test_project.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from unittest.mock import Mock

import pytest
from rest_framework import serializers

from sentry.api.serializers.rest_framework.list import EmptyListField
from sentry.api.serializers.rest_framework.project import ProjectField
from sentry.testutils.cases import TestCase

Expand Down Expand Up @@ -38,3 +40,40 @@ class ProjectSerializer(serializers.Serializer):

assert not serializer.is_valid()
assert serializer.errors == {"project": ["Invalid project"]}


class EmptyListFieldTest(TestCase):
def test_empty_string_is_an_empty_list(self) -> None:
field = EmptyListField(child=serializers.CharField(allow_blank=True))

assert field.to_internal_value("") == []

def test_default_child_preserves_arbitrary_items(self) -> None:
field = EmptyListField()

assert field.to_internal_value([1, "value"]) == [1, "value"]

def test_integer_child_converts_values(self) -> None:
field = EmptyListField(child=serializers.IntegerField())

assert field.to_internal_value(["1"]) == [1]

def test_string_child_validates_values(self) -> None:
field = EmptyListField(child=serializers.CharField())

assert field.to_internal_value([1]) == ["1"]

def test_invalid_values_keep_list_field_validation(self) -> None:
field = EmptyListField(child=serializers.IntegerField())

with pytest.raises(serializers.ValidationError):
field.to_internal_value(["invalid"])

with pytest.raises(serializers.ValidationError):
field.to_internal_value("invalid")

def test_non_empty_string_is_not_split_into_items(self) -> None:
field = EmptyListField(child=serializers.CharField())

with pytest.raises(serializers.ValidationError):
field.to_internal_value("abc")
Loading