from datetime import datetime from decimal import Decimal from unittest import mock import pytest from django.conf import settings from django_countries.fields import Country from django_scopes import scopes_disabled from pytz import UTC from pretix.base.models import ( Event, InvoiceAddress, Order, OrderPosition, SeatingPlan, ) from pretix.base.models.orders import OrderFee @pytest.fixture def variations(item): v = list() v.append(item.variations.create(value="ChildA1")) v.append(item.variations.create(value="ChildA2")) return v @pytest.fixture def order(event, item, taxrule): testtime = datetime(2017, 12, 1, 10, 0, 0, tzinfo=UTC) with mock.patch('django.utils.timezone.now') as mock_now: mock_now.return_value = testtime o = Order.objects.create( code='FOO', event=event, email='dummy@dummy.test', status=Order.STATUS_PENDING, secret="k24fiuwvu8kxz3y1", datetime=datetime(2017, 12, 1, 10, 0, 0, tzinfo=UTC), expires=datetime(2017, 12, 10, 10, 0, 0, tzinfo=UTC), total=23, locale='en' ) o.fees.create(fee_type=OrderFee.FEE_TYPE_PAYMENT, value=Decimal('0.25'), tax_rate=Decimal('19.00'), tax_value=Decimal('0.05'), tax_rule=taxrule) InvoiceAddress.objects.create(order=o, company="Sample company", country=Country('NZ')) return o @pytest.fixture def order_position(item, order, taxrule, variations): op = OrderPosition.objects.create( order=order, item=item, variation=variations[0], tax_rule=taxrule, tax_rate=taxrule.rate, tax_value=Decimal("3"), price=Decimal("23"), attendee_name_parts={'full_name': "Peter"}, secret="z3fsn8jyufm5kpk768q69gkbyr5f4h6w" ) return op TEST_EVENT_RES = { "name": {"en": "Dummy"}, "live": False, "testmode": False, "currency": "EUR", "date_from": "2017-12-27T10:00:00Z", "date_to": None, "date_admission": None, "is_public": True, "presale_start": None, "presale_end": None, "location": None, "geo_lat": None, "geo_lon": None, "slug": "dummy", "has_subevents": False, "seating_plan": None, "seat_category_mapping": {}, "meta_data": {"type": "Conference"}, 'timezone': 'Europe/Berlin', 'plugins': [ 'pretix.plugins.banktransfer', 'pretix.plugins.ticketoutputpdf' ], 'item_meta_properties': { 'day': 'Monday', } } @pytest.fixture def item(event): return event.items.create(name="Budget Ticket", default_price=23) @pytest.fixture def free_item(event): return event.items.create(name="Free Ticket", default_price=0) @pytest.fixture def free_quota(event, free_item): q = event.quotas.create(name="Budget Quota", size=200) q.items.add(free_item) return q @pytest.mark.django_db def test_event_list(token_client, organizer, event): resp = token_client.get('/api/v1/organizers/{}/events/'.format(organizer.slug)) assert resp.status_code == 200 assert TEST_EVENT_RES == resp.data['results'][0] resp = token_client.get('/api/v1/organizers/{}/events/?live=true'.format(organizer.slug)) assert resp.status_code == 200 assert [] == resp.data['results'] resp = token_client.get('/api/v1/organizers/{}/events/?live=false'.format(organizer.slug)) assert resp.status_code == 200 assert [TEST_EVENT_RES] == resp.data['results'] resp = token_client.get('/api/v1/organizers/{}/events/?is_public=false'.format(organizer.slug)) assert resp.status_code == 200 assert [] == resp.data['results'] resp = token_client.get('/api/v1/organizers/{}/events/?is_public=true'.format(organizer.slug)) assert resp.status_code == 200 assert [TEST_EVENT_RES] == resp.data['results'] resp = token_client.get('/api/v1/organizers/{}/events/?has_subevents=true'.format(organizer.slug)) assert resp.status_code == 200 assert [] == resp.data['results'] resp = token_client.get('/api/v1/organizers/{}/events/?has_subevents=false'.format(organizer.slug)) assert resp.status_code == 200 assert [TEST_EVENT_RES] == resp.data['results'] resp = token_client.get('/api/v1/organizers/{}/events/?ends_after=2017-12-27T10:01:00Z'.format(organizer.slug)) assert resp.status_code == 200 assert [] == resp.data['results'] resp = token_client.get('/api/v1/organizers/{}/events/?ends_after=2017-12-27T09:59:59Z'.format(organizer.slug)) assert resp.status_code == 200 assert [TEST_EVENT_RES] == resp.data['results'] @pytest.mark.django_db def test_event_list_filter(token_client, organizer, event): resp = token_client.get('/api/v1/organizers/{}/events/?attr[type]=Conference'.format(organizer.slug)) assert resp.status_code == 200 assert resp.data['count'] == 1 resp = token_client.get('/api/v1/organizers/{}/events/?attr[type]='.format(organizer.slug)) assert resp.status_code == 200 assert resp.data['count'] == 0 @pytest.mark.django_db def test_event_get(token_client, organizer, event): resp = token_client.get('/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug)) assert resp.status_code == 200 assert TEST_EVENT_RES == resp.data @pytest.mark.django_db def test_event_create(token_client, organizer, event, meta_prop): resp = token_client.post( '/api/v1/organizers/{}/events/'.format(organizer.slug), { "name": { "de": "Demo Konference 2020 Test", "en": "Demo Conference 2020 Test" }, "live": False, "currency": "EUR", "date_from": "2017-12-27T10:00:00Z", "date_to": "2017-12-28T10:00:00Z", "date_admission": None, "is_public": False, "presale_start": None, "presale_end": None, "location": None, "slug": "2030", "meta_data": { meta_prop.name: "Conference" }, "seat_category_mapping": {}, "timezone": "Europe/Amsterdam" }, format='json' ) assert resp.status_code == 201 with scopes_disabled(): assert not organizer.events.get(slug="2030").testmode assert organizer.events.get(slug="2030").meta_values.filter( property__name=meta_prop.name, value="Conference" ).exists() assert organizer.events.get(slug="2030").plugins == settings.PRETIX_PLUGINS_DEFAULT assert organizer.events.get(slug="2030").settings.timezone == "Europe/Amsterdam" resp = token_client.post( '/api/v1/organizers/{}/events/'.format(organizer.slug), { "name": { "de": "Demo Konference 2020 Test", "en": "Demo Conference 2020 Test" }, "live": False, "currency": "EUR", "date_from": "2017-12-27T10:00:00Z", "date_to": "2017-12-28T10:00:00Z", "date_admission": None, "is_public": False, "presale_start": None, "presale_end": None, "location": None, "slug": "2020", "meta_data": { "foo": "bar" } }, format='json' ) assert resp.status_code == 400 assert resp.content.decode() == '{"meta_data":["Meta data property \'foo\' does not exist."]}' resp = token_client.post( '/api/v1/organizers/{}/events/'.format(organizer.slug), { "name": { "de": "Demo Konference 2020 Test", "en": "Demo Conference 2020 Test" }, "live": False, "currency": "EUR", "date_from": "2017-12-27T10:00:00Z", "date_to": "2017-12-28T10:00:00Z", "date_admission": None, "is_public": False, "presale_start": None, "presale_end": None, "location": None, "slug": event.slug, "meta_data": { "type": "Conference" } }, format='json' ) assert resp.status_code == 400 assert resp.content.decode() == '{"slug":["This slug has already been used for a different event."]}' resp = token_client.post( '/api/v1/organizers/{}/events/'.format(organizer.slug), { "name": { "de": "Demo Konference 2020 Test", "en": "Demo Conference 2020 Test" }, "live": True, "currency": "EUR", "date_from": "2017-12-27T10:00:00Z", "date_to": "2017-12-28T10:00:00Z", "date_admission": None, "is_public": False, "presale_start": None, "presale_end": None, "location": None, "slug": "2031", "meta_data": { "type": "Conference" } }, format='json' ) assert resp.status_code == 400 assert resp.content.decode() == '{"live":["Events cannot be created as \'live\'. Quotas and payment must be added ' \ 'to the event before sales can go live."]}' @pytest.mark.django_db def test_event_create_with_clone(token_client, organizer, event, meta_prop): resp = token_client.post( '/api/v1/organizers/{}/events/{}/clone/'.format(organizer.slug, event.slug), { "name": { "de": "Demo Konference 2020 Test", "en": "Demo Conference 2020 Test" }, "live": False, "testmode": True, "currency": "EUR", "date_from": "2018-12-27T10:00:00Z", "date_to": "2018-12-28T10:00:00Z", "date_admission": None, "is_public": False, "presale_start": None, "presale_end": None, "location": None, "slug": "2030", "meta_data": { "type": "Conference" }, "plugins": [ "pretix.plugins.ticketoutputpdf" ], "timezone": "Europe/Vienna" }, format='json' ) assert resp.status_code == 201 with scopes_disabled(): cloned_event = Event.objects.get(organizer=organizer.pk, slug='2030') assert cloned_event.plugins == 'pretix.plugins.ticketoutputpdf' assert cloned_event.is_public is False assert cloned_event.testmode assert organizer.events.get(slug="2030").meta_values.filter( property__name=meta_prop.name, value="Conference" ).exists() assert cloned_event.settings.timezone == "Europe/Vienna" resp = token_client.post( '/api/v1/organizers/{}/events/{}/clone/'.format(organizer.slug, event.slug), { "name": { "de": "Demo Konference 2020 Test", "en": "Demo Conference 2020 Test" }, "live": False, "currency": "EUR", "date_from": "2018-12-27T10:00:00Z", "date_to": "2018-12-28T10:00:00Z", "date_admission": None, "presale_start": None, "presale_end": None, "location": None, "slug": "2031", "meta_data": { "type": "Conference" } }, format='json' ) assert resp.status_code == 201 with scopes_disabled(): cloned_event = Event.objects.get(organizer=organizer.pk, slug='2031') assert cloned_event.plugins == "pretix.plugins.banktransfer,pretix.plugins.ticketoutputpdf" assert cloned_event.is_public is True assert organizer.events.get(slug="2031").meta_values.filter( property__name=meta_prop.name, value="Conference" ).exists() resp = token_client.post( '/api/v1/organizers/{}/events/{}/clone/'.format(organizer.slug, event.slug), { "name": { "de": "Demo Konference 2020 Test", "en": "Demo Conference 2020 Test" }, "live": False, "currency": "EUR", "date_from": "2018-12-27T10:00:00Z", "date_to": "2018-12-28T10:00:00Z", "date_admission": None, "presale_start": None, "presale_end": None, "location": None, "slug": "2032", "plugins": [] }, format='json' ) assert resp.status_code == 201 with scopes_disabled(): cloned_event = Event.objects.get(organizer=organizer.pk, slug='2032') assert cloned_event.plugins == "" @pytest.mark.django_db def test_event_put_with_clone(token_client, organizer, event, meta_prop): resp = token_client.put( '/api/v1/organizers/{}/events/{}/clone/'.format(organizer.slug, event.slug), {}, format='json' ) assert resp.status_code == 405 @pytest.mark.django_db def test_event_patch_with_clone(token_client, organizer, event, meta_prop): resp = token_client.patch( '/api/v1/organizers/{}/events/{}/clone/'.format(organizer.slug, event.slug), {}, format='json' ) assert resp.status_code == 405 @pytest.mark.django_db def test_event_delete_with_clone(token_client, organizer, event, meta_prop): resp = token_client.delete( '/api/v1/organizers/{}/events/{}/clone/'.format(organizer.slug, event.slug), {}, format='json' ) assert resp.status_code == 405 @pytest.mark.django_db def test_event_update(token_client, organizer, event, item, meta_prop): resp = token_client.patch( '/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug), { "date_from": "2018-12-27T10:00:00Z", "date_to": "2018-12-28T10:00:00Z", "currency": "DKK", }, format='json' ) assert resp.status_code == 200 with scopes_disabled(): event = Event.objects.get(organizer=organizer.pk, slug=resp.data['slug']) assert event.currency == "DKK" assert organizer.events.get(slug=resp.data['slug']).meta_values.filter( property__name=meta_prop.name, value="Conference" ).exists() resp = token_client.patch( '/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug), { "date_from": "2017-12-27T10:00:00Z", "date_to": "2017-12-26T10:00:00Z" }, format='json' ) assert resp.status_code == 400 assert resp.content.decode() == '{"non_field_errors":["The event cannot end before it starts."]}' resp = token_client.patch( '/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug), { "presale_start": "2017-12-27T10:00:00Z", "presale_end": "2017-12-26T10:00:00Z" }, format='json' ) assert resp.status_code == 400 assert resp.content.decode() == '{"non_field_errors":["The event\'s presale cannot end before it starts."]}' resp = token_client.patch( '/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug), { "slug": "testing" }, format='json' ) assert resp.status_code == 400 assert resp.content.decode() == '{"slug":["The event slug cannot be changed."]}' resp = token_client.patch( '/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug), { "has_subevents": True }, format='json' ) assert resp.status_code == 400 assert resp.content.decode() == '{"has_subevents":["Once created an event cannot change between an series and a ' \ 'single event."]}' resp = token_client.patch( '/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug), { "meta_data": { meta_prop.name: "Workshop" } }, format='json' ) assert resp.status_code == 200 with scopes_disabled(): assert organizer.events.get(slug=resp.data['slug']).meta_values.filter( property__name=meta_prop.name, value="Workshop" ).exists() resp = token_client.patch( '/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug), { "meta_data": { } }, format='json' ) assert resp.status_code == 200 with scopes_disabled(): assert not organizer.events.get(slug=resp.data['slug']).meta_values.filter( property__name=meta_prop.name ).exists() resp = token_client.patch( '/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug), { "meta_data": { "test": "test" } }, format='json' ) assert resp.status_code == 400 assert resp.content.decode() == '{"meta_data":["Meta data property \'test\' does not exist."]}' resp = token_client.patch( '/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug), { "item_meta_properties": { "Foo": "Bar" } }, format='json' ) assert resp.status_code == 200 with scopes_disabled(): assert organizer.events.get(slug=resp.data['slug']).item_meta_properties.filter( name="Foo", default="Bar" ).exists() resp = token_client.patch( '/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug), { "item_meta_properties": { } }, format='json' ) assert resp.status_code == 200 with scopes_disabled(): assert not organizer.events.get(slug=resp.data['slug']).item_meta_properties.filter( name="Foo" ).exists() @pytest.mark.django_db def test_event_test_mode(token_client, organizer, event): resp = token_client.patch( '/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug), { "testmode": True }, format='json' ) assert resp.status_code == 200 event.refresh_from_db() assert event.testmode resp = token_client.patch( '/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug), { "testmode": False }, format='json' ) assert resp.status_code == 200 event.refresh_from_db() assert not event.testmode @pytest.mark.django_db def test_event_update_live_no_product(token_client, organizer, event): resp = token_client.patch( '/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug), { "live": True }, format='json' ) assert resp.status_code == 400 assert resp.content.decode() == '{"live":["You need to configure at least one quota to sell anything."]}' @pytest.mark.django_db def test_event_update_live_no_payment_method(token_client, organizer, event, item, free_quota): resp = token_client.patch( '/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug), { "live": True }, format='json' ) assert resp.status_code == 400 assert resp.content.decode() == '{"live":["You have configured at least one paid product but have not enabled any ' \ 'payment methods."]}' @pytest.mark.django_db def test_event_update_live_free_product(token_client, organizer, event, free_item, free_quota): resp = token_client.patch( '/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug), { "live": True }, format='json' ) assert resp.status_code == 200 @pytest.mark.django_db def test_event_update_plugins(token_client, organizer, event, free_item, free_quota): resp = token_client.patch( '/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug), { "plugins": [ "pretix.plugins.ticketoutputpdf", "pretix.plugins.pretixdroid" ] }, format='json' ) assert resp.status_code == 200 assert set(resp.data.get('plugins')) == { "pretix.plugins.ticketoutputpdf", "pretix.plugins.pretixdroid" } resp = token_client.patch( '/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug), { "plugins": { "pretix.plugins.banktransfer" } }, format='json' ) assert resp.status_code == 200 assert resp.data.get('plugins') == [ "pretix.plugins.banktransfer" ] resp = token_client.patch( '/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug), { "plugins": { "pretix.plugins.test" } }, format='json' ) assert resp.status_code == 400 assert resp.content.decode() == '{"plugins":["Unknown plugin: \'pretix.plugins.test\'."]}' @pytest.mark.django_db def test_event_detail(token_client, organizer, event, team): team.all_events = True team.save() resp = token_client.get('/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug)) assert resp.status_code == 200 assert TEST_EVENT_RES == resp.data @pytest.mark.django_db def test_event_delete(token_client, organizer, event): resp = token_client.delete('/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug)) assert resp.status_code == 204 with scopes_disabled(): assert not organizer.events.filter(pk=event.id).exists() @pytest.mark.django_db def test_event_with_order_position_not_delete(token_client, organizer, event, item, order_position): resp = token_client.delete('/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug)) assert resp.status_code == 403 assert resp.content.decode() == '{"detail":"The event can not be deleted as it already contains orders. Please ' \ 'set \'live\' to false to hide the event and take the shop offline instead."}' with scopes_disabled(): assert organizer.events.filter(pk=event.id).exists() @pytest.fixture def seatingplan(event, organizer, item): return SeatingPlan.objects.create( name="Plan", organizer=organizer, layout="""{ "name": "Grosser Saal", "categories": [ { "name": "Stalls", "color": "red" } ], "zones": [ { "name": "Main Area", "position": { "x": 0, "y": 0 }, "rows": [ { "row_number": "0", "seats": [ { "seat_guid": "0-0", "seat_number": "0-0", "position": { "x": 0, "y": 0 }, "category": "Stalls" }, { "seat_guid": "0-1", "seat_number": "0-1", "position": { "x": 33, "y": 0 }, "category": "Stalls" }, { "seat_guid": "0-2", "seat_number": "0-2", "position": { "x": 66, "y": 0 }, "category": "Stalls" } ], "position": { "x": 0, "y": 0 } } ] } ], "size": { "width": 600, "height": 400 } }""" ) @pytest.mark.django_db def test_event_update_seating(token_client, organizer, event, item, seatingplan): resp = token_client.patch( '/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug), { "seating_plan": seatingplan.pk, "seat_category_mapping": { "Stalls": item.pk } }, format='json' ) assert resp.status_code == 200 event.refresh_from_db() assert event.seating_plan == seatingplan with scopes_disabled(): assert event.seats.count() == 3 assert event.seats.filter(product=item).count() == 3 m = event.seat_category_mappings.get() assert m.layout_category == 'Stalls' assert m.product == item @pytest.mark.django_db def test_event_update_seating_invalid_product(token_client, organizer, event, item, seatingplan): resp = token_client.patch( '/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug), { "seating_plan": seatingplan.pk, "seat_category_mapping": { "Stalls": item.pk + 2 } }, format='json' ) assert resp.status_code == 400 assert resp.content.decode() == '{"seat_category_mapping":["Item \'%d\' does not exist."]}' % (item.pk + 2) @pytest.mark.django_db def test_event_update_seating_change_mapping(token_client, organizer, event, item, seatingplan): resp = token_client.patch( '/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug), { "seating_plan": seatingplan.pk, "seat_category_mapping": { "Stalls": item.pk } }, format='json' ) assert resp.status_code == 200 event.refresh_from_db() assert event.seating_plan == seatingplan with scopes_disabled(): assert event.seats.count() == 3 assert event.seats.filter(product=item).count() == 3 m = event.seat_category_mappings.get() assert m.layout_category == 'Stalls' assert m.product == item resp = token_client.patch( '/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug), { "seat_category_mapping": { "VIP": item.pk, } }, format='json' ) assert resp.status_code == 200 event.refresh_from_db() assert event.seating_plan == seatingplan with scopes_disabled(): assert event.seats.count() == 3 m = event.seat_category_mappings.get() assert event.seats.filter(product=None).count() == 3 assert m.layout_category == 'VIP' assert m.product == item @pytest.mark.django_db def test_remove_seating(token_client, organizer, event, item, seatingplan): resp = token_client.patch( '/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug), { "seating_plan": seatingplan.pk, "seat_category_mapping": { "Stalls": item.pk } }, format='json' ) assert resp.status_code == 200 event.refresh_from_db() assert event.seating_plan == seatingplan with scopes_disabled(): assert event.seats.count() == 3 assert event.seat_category_mappings.count() == 1 resp = token_client.patch( '/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug), { "seating_plan": None }, format='json' ) assert resp.status_code == 200 event.refresh_from_db() assert event.seating_plan is None with scopes_disabled(): assert event.seats.count() == 0 assert event.seat_category_mappings.count() == 0 @pytest.mark.django_db def test_remove_seating_forbidden(token_client, organizer, event, item, seatingplan, order_position): resp = token_client.patch( '/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug), { "seating_plan": seatingplan.pk, "seat_category_mapping": { "Stalls": item.pk } }, format='json' ) assert resp.status_code == 200 event.refresh_from_db() assert event.seating_plan == seatingplan with scopes_disabled(): assert event.seats.count() == 3 assert event.seat_category_mappings.count() == 1 order_position.seat = event.seats.first() order_position.save() resp = token_client.patch( '/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug), { "seating_plan": None }, format='json' ) assert resp.status_code == 400 assert resp.content.decode() == '{"seating_plan":["You can not change the plan since seat \\"0-0\\" is not ' \ 'present in the new plan and is already sold."]}' @pytest.mark.django_db def test_no_seating_for_series(token_client, organizer, event, item, seatingplan, order_position): event.has_subevents = True event.save() resp = token_client.patch( '/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug), { "seating_plan": seatingplan.pk, "seat_category_mapping": { "Stalls": item.pk } }, format='json' ) assert resp.status_code == 400 assert resp.content.decode() == '{"non_field_errors":["Event series should not directly be assigned a seating plan."]}' @pytest.mark.django_db def test_event_create_with_seating(token_client, organizer, event, meta_prop, seatingplan): resp = token_client.post( '/api/v1/organizers/{}/events/'.format(organizer.slug), { "name": { "de": "Demo Konference 2020 Test", "en": "Demo Conference 2020 Test" }, "live": False, "currency": "EUR", "date_from": "2017-12-27T10:00:00Z", "date_to": "2017-12-28T10:00:00Z", "date_admission": None, "is_public": False, "presale_start": None, "presale_end": None, "location": None, "slug": "2030", "seating_plan": seatingplan.pk, "meta_data": { meta_prop.name: "Conference" } }, format='json' ) assert resp.status_code == 201 with scopes_disabled(): event = Event.objects.get(slug=resp.data['slug']) assert event.seating_plan == seatingplan assert event.seats.count() == 3 assert event.seat_category_mappings.count() == 0 @pytest.mark.django_db def test_event_create_with_seating_maps(token_client, organizer, event, meta_prop, seatingplan): resp = token_client.post( '/api/v1/organizers/{}/events/'.format(organizer.slug), { "name": { "de": "Demo Konference 2020 Test", "en": "Demo Conference 2020 Test" }, "live": False, "currency": "EUR", "date_from": "2017-12-27T10:00:00Z", "date_to": "2017-12-28T10:00:00Z", "date_admission": None, "is_public": False, "presale_start": None, "presale_end": None, "location": None, "slug": "2030", "seating_plan": seatingplan.pk, "seat_category_mapping": { "Foo": 1, }, "meta_data": { meta_prop.name: "Conference" } }, format='json' ) assert resp.status_code == 400 assert resp.content.decode() == '{"seat_category_mapping":["You cannot specify seat category mappings on event creation."]}' @pytest.mark.django_db def test_get_event_settings(token_client, organizer, event): event.settings.imprint_url = "https://example.org" resp = token_client.get( '/api/v1/organizers/{}/events/{}/settings/'.format(organizer.slug, event.slug), ) assert resp.status_code == 200 assert resp.data['imprint_url'] == "https://example.org" resp = token_client.get( '/api/v1/organizers/{}/events/{}/settings/?explain=true'.format(organizer.slug, event.slug), ) assert resp.status_code == 200 assert resp.data['imprint_url'] == { "value": "https://example.org", "label": "Imprint URL", "help_text": "This should point e.g. to a part of your website that has your contact details and legal " "information." } @pytest.mark.django_db def test_patch_event_settings(token_client, organizer, event): organizer.settings.imprint_url = 'https://example.org' resp = token_client.patch( '/api/v1/organizers/{}/events/{}/settings/'.format(organizer.slug, event.slug), { 'imprint_url': 'https://example.com' }, format='json' ) assert resp.status_code == 200 assert resp.data['imprint_url'] == "https://example.com" event.settings.flush() assert event.settings.imprint_url == 'https://example.com' resp = token_client.patch( '/api/v1/organizers/{}/events/{}/settings/'.format(organizer.slug, event.slug), { 'imprint_url': None, }, format='json' ) assert resp.status_code == 200 assert resp.data['imprint_url'] == "https://example.org" event.settings.flush() assert event.settings.imprint_url == 'https://example.org' resp = token_client.put( '/api/v1/organizers/{}/events/{}/settings/'.format(organizer.slug, event.slug), { 'imprint_url': 'invalid' }, format='json' ) assert resp.status_code == 405 @pytest.mark.django_db def test_patch_event_settings_validation(token_client, organizer, event): resp = token_client.patch( '/api/v1/organizers/{}/events/{}/settings/'.format(organizer.slug, event.slug), { 'imprint_url': 'invalid' }, format='json' ) assert resp.status_code == 400 assert resp.data == { 'imprint_url': ['Enter a valid URL.'] } resp = token_client.patch( '/api/v1/organizers/{}/events/{}/settings/'.format(organizer.slug, event.slug), { 'invoice_address_required': True, 'invoice_address_asked': False, }, format='json' ) assert resp.status_code == 400 assert resp.data == { 'invoice_address_required': ['You have to ask for invoice addresses if you want to make them required.'] } resp = token_client.patch( '/api/v1/organizers/{}/events/{}/settings/'.format(organizer.slug, event.slug), { 'cancel_allow_user_until': 'RELDATE/3/12:00/foobar/', 'invoice_address_asked': False, }, format='json' ) assert resp.status_code == 400 assert resp.data == { 'cancel_allow_user_until': ['Invalid relative date'] }