validate and add tests

This commit is contained in:
Richard Schreiber
2026-09-18 12:35:41 +02:00
parent 71153ccdf4
commit 403efcf38c
3 changed files with 172 additions and 0 deletions
+17
View File
@@ -650,3 +650,20 @@ class EventMetaPropertiesSerializer(I18nAwareModelSerializer):
'id', 'name', 'default', 'required', 'protected', 'filter_public', 'public_label', 'filter_allowed',
'choices'
)
def validate(self, data):
data = super().validate(data)
full_data = self.to_internal_value(self.to_representation(self.instance)) if self.instance else {}
full_data.update(data)
choices = full_data.get("choices")
if choices is not None and not isinstance(choices, dict):
raise ValidationError("Choices need to be a dictionary or null.")
default = full_data.get("default")
if choices and default and default not in choices.keys():
raise ValidationError("You cannot set a default value that is not a valid value.")
if not choices and "choices" in data:
# normalize empty dict to None
data["choices"] = None
return data
+153
View File
@@ -0,0 +1,153 @@
#
# This file is part of pretix (Community Edition).
#
# Copyright (C) 2014-2020 Raphael Michel and contributors
# Copyright (C) 2020-today pretix GmbH and contributors
#
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
# Public License as published by the Free Software Foundation in version 3 of the License.
#
# ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are
# applicable granting you additional permissions and placing additional restrictions on your usage of this software.
# Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive
# this file, see <https://pretix.eu/about/en/license>.
#
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
# <https://www.gnu.org/licenses/>.
#
import pytest
from django_scopes import scopes_disabled
@pytest.fixture
def event_meta_property(organizer):
return organizer.meta_properties.create(
name="Color",
default="Red",
required=False,
choices=None,
)
TEST_TYPE_RES = {
"name": "Color",
"default": "Red",
"required": False,
"choices": None,
'filter_allowed': True,
'filter_public': False,
'protected': False,
'public_label': None,
}
@pytest.mark.django_db
def test_meta_property_list(token_client, organizer, event_meta_property):
res = dict(TEST_TYPE_RES)
resp = token_client.get('/api/v1/organizers/{}/event_meta_properties/'
.format(organizer.slug))
assert resp.status_code == 200
event_meta_property.refresh_from_db()
res["id"] = event_meta_property.pk
assert res in resp.data['results']
assert len(resp.data['results']) == 1
@pytest.mark.django_db
def test_meta_property_detail(token_client, organizer, event_meta_property):
res = TEST_TYPE_RES
resp = token_client.get('/api/v1/organizers/{}/event_meta_properties/{}/'
.format(organizer.slug, event_meta_property.pk))
assert resp.status_code == 200
event_meta_property.refresh_from_db()
res["id"] = event_meta_property.pk
assert res == resp.data
@pytest.mark.django_db
def test_meta_property_create(token_client, organizer):
resp = token_client.post(
'/api/v1/organizers/{}/event_meta_properties/'.format(organizer.slug),
format='json',
data={
"name": "Color",
"default": "Red",
"required": False,
"choices": ["Red", "Green", "Blue"]
}
)
assert resp.status_code == 400
choices = {"r": "Red", "g": "Green", "b": "Blue"}
resp = token_client.post(
'/api/v1/organizers/{}/event_meta_properties/'.format(organizer.slug),
format='json',
data={
"name": "Color",
"default": "Red",
"required": False,
"choices": choices,
}
)
assert resp.status_code == 400
resp = token_client.post(
'/api/v1/organizers/{}/event_meta_properties/'.format(organizer.slug),
format='json',
data={
"name": "Color",
"default": "r",
"required": False,
"choices": choices,
}
)
assert resp.status_code == 201
with scopes_disabled():
event_meta_property = organizer.meta_properties.get(id=resp.data['id'])
assert event_meta_property.name == "Color"
assert event_meta_property.default == "r"
assert event_meta_property.choices == choices
assert not event_meta_property.required
assert len(organizer.meta_properties.all()) == 1
@pytest.mark.django_db
def test_meta_property_patch(token_client, organizer, event_meta_property):
resp = token_client.patch(
'/api/v1/organizers/{}/event_meta_properties/{}/'
.format(organizer.slug, event_meta_property.pk),
format='json',
data={
# existing default is not in choices
"choices": {'k': 'Black'},
}
)
assert resp.status_code == 400
resp = token_client.patch(
'/api/v1/organizers/{}/event_meta_properties/{}/'
.format(organizer.slug, event_meta_property.pk),
format='json',
data={
"required": True,
"choices": None,
}
)
assert resp.status_code == 200
event_meta_property.refresh_from_db()
assert event_meta_property.required
assert event_meta_property.choices is None
@pytest.mark.django_db
def test_meta_property_delete(token_client, organizer, event_meta_property):
resp = token_client.delete(
'/api/v1/organizers/{}/event_meta_properties/{}/'
.format(organizer.slug, event_meta_property.pk),
)
assert resp.status_code == 204
assert len(organizer.meta_properties.all()) == 0
+2
View File
@@ -223,6 +223,8 @@ org_permission_sub_urls = [
('post', 'organizer.customers:write', 'customers/1/anonymize/', 404),
('put', 'organizer.customers:write', 'customers/1/', 404),
('delete', 'organizer.customers:write', 'customers/1/', 404),
('post', 'organizer.settings.general:write', 'event_meta_properties/', 400),
('patch', 'organizer.settings.general:write', 'event_meta_properties/1/', 200),
('get', 'organizer.customers:read', 'memberships/', 200),
('post', 'organizer.customers:write', 'memberships/', 400),
('get', 'organizer.customers:read', 'memberships/1/', 404),