Files
pretix_original/src/tests/presale/test_widget.py

953 lines
51 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#
# This file is part of pretix (Community Edition).
#
# Copyright (C) 2014-2020 Raphael Michel and contributors
# Copyright (C) 2020-2021 rami.io 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 datetime
import json
from decimal import Decimal
from bs4 import BeautifulSoup
from django.conf import settings
from django.test import TestCase, override_settings
from django.utils.timezone import now
from django_scopes import scopes_disabled
from freezegun import freeze_time
from pretix.base.models import Order, OrderPosition
from .test_cart import CartTestMixin
class WidgetCartTest(CartTestMixin, TestCase):
@scopes_disabled()
def setUp(self):
super().setUp()
self.order = Order.objects.create(
status=Order.STATUS_PENDING,
event=self.event,
email='admin@localhost',
datetime=now() - datetime.timedelta(days=3),
expires=now() + datetime.timedelta(days=11),
total=Decimal("23"),
locale='en',
sales_channel=self.orga.sales_channels.get(identifier="web"),
)
self.ticket_pos = OrderPosition.objects.create(
order=self.order,
item=self.ticket,
variation=None,
price=Decimal("23"),
attendee_name_parts={'full_name': "Peter"}
)
def test_iframe_entry_view_wrapper(self):
self.event.settings.locales = ["de", "en"]
r = self.client.get('/%s/%s/?iframe=1&locale=de' % (self.orga.slug, self.event.slug), headers={
"Accept-Language": "en-GB,en-US;q=0.9,en;q=0.8",
})
assert 'iframe_session' in self.client.session
assert self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value == "de"
assert r.headers["Content-Language"] == "de"
def test_allow_frame_if_namespaced(self):
response = self.client.get('/%s/%s/' % (self.orga.slug, self.event.slug))
assert 'X-Frame-Options' in response
response = self.client.get('/%s/%s/w/aaaaaaaaaaaaaaaa/' % (self.orga.slug, self.event.slug))
assert 'X-Frame-Options' not in response
response = self.client.get('/%s/%s/waitinglist' % (self.orga.slug, self.event.slug))
assert 'X-Frame-Options' in response
response = self.client.get('/%s/%s/w/aaaaaaaaaaaaaaaa/waitinglist' % (self.orga.slug, self.event.slug))
assert 'X-Frame-Options' not in response
def test_allow_frame_on_order(self):
response = self.client.get('/%s/%s/order/%s/%s/' % (self.orga.slug, self.event.slug, self.order.code,
self.order.secret))
assert 'X-Frame-Options' not in response
response = self.client.get('/%s/%s/order/%s/%s/modify' % (self.orga.slug, self.event.slug, self.order.code,
self.order.secret))
assert 'X-Frame-Options' not in response
response = self.client.get('/%s/%s/order/%s/%s/pay/change' % (self.orga.slug, self.event.slug, self.order.code,
self.order.secret))
assert 'X-Frame-Options' not in response
response = self.client.get('/%s/%s/order/%s/%s/cancel' % (self.orga.slug, self.event.slug, self.order.code,
self.order.secret))
assert 'X-Frame-Options' not in response
def test_allow_cors_if_namespaced(self):
response = self.client.post('/%s/%s/cart/add' % (self.orga.slug, self.event.slug), {
'item_%d' % self.ticket.id: '1',
'ajax': 1
})
assert 'Access-Control-Allow-Origin' not in response
response = self.client.post('/%s/%s/w/aaaaaaaaaaaaaaaa/cart/add' % (self.orga.slug, self.event.slug), {
'item_%d' % self.ticket.id: '1',
'ajax': 1
})
assert response['Access-Control-Allow-Origin'] == '*'
def test_cart_isolation(self):
response = self.client.post('/%s/%s/cart/add' % (self.orga.slug, self.event.slug), {
'item_%d' % self.ticket.id: '1'
}, follow=True)
self.assertRedirects(response, '/%s/%s/?require_cookie=true' % (self.orga.slug, self.event.slug),
target_status_code=200)
doc = BeautifulSoup(response.rendered_content, "lxml")
assert len(doc.select('.cart .cart-row')) == 2
self.assertIn('Early-bird', doc.select('.cart .cart-row')[0].select('strong')[0].text)
self.assertIn('1', doc.select('.cart .cart-row')[0].select('.count')[0].text)
self.assertIn('23', doc.select('.cart .cart-row')[0].select('.price')[0].text)
self.assertIn('23', doc.select('.cart .cart-row')[0].select('.price')[1].text)
response = self.client.get('/%s/%s/w/aaaaaaaaaaaaaaaa/' % (self.orga.slug, self.event.slug))
doc = BeautifulSoup(response.rendered_content, "lxml")
assert len(doc.select('.cart .cart-row')) == 0
response = self.client.post('/%s/%s/w/aaaaaaaaaaaaaaaa/cart/add' % (self.orga.slug, self.event.slug), {
'item_%d' % self.ticket.id: '1'
}, follow=True)
self.assertRedirects(response, '/%s/%s/w/aaaaaaaaaaaaaaaa/?require_cookie=true' % (self.orga.slug, self.event.slug),
target_status_code=200)
doc = BeautifulSoup(response.rendered_content, "lxml")
assert len(doc.select('.cart .cart-row')) == 2
self.assertIn('Early-bird', doc.select('.cart .cart-row')[0].select('strong')[0].text)
self.assertIn('1', doc.select('.cart .cart-row')[0].select('.count')[0].text)
self.assertIn('23', doc.select('.cart .cart-row')[0].select('.price')[0].text)
self.assertIn('23', doc.select('.cart .cart-row')[0].select('.price')[1].text)
response = self.client.get('/%s/%s/w/aaaaaaaaaaaaaaab/' % (self.orga.slug, self.event.slug))
doc = BeautifulSoup(response.rendered_content, "lxml")
assert len(doc.select('.cart .cart-row')) == 0
response = self.client.post('/%s/%s/w/aaaaaaaaaaaaaaab/cart/add' % (self.orga.slug, self.event.slug), {
'item_%d' % self.ticket.id: '1'
}, follow=True)
self.assertRedirects(response, '/%s/%s/w/aaaaaaaaaaaaaaab/?require_cookie=true' % (self.orga.slug, self.event.slug),
target_status_code=200)
doc = BeautifulSoup(response.rendered_content, "lxml")
assert len(doc.select('.cart .cart-row')) == 2
self.assertIn('Early-bird', doc.select('.cart .cart-row')[0].select('strong')[0].text)
self.assertIn('1', doc.select('.cart .cart-row')[0].select('.count')[0].text)
self.assertIn('23', doc.select('.cart .cart-row')[0].select('.price')[0].text)
self.assertIn('23', doc.select('.cart .cart-row')[0].select('.price')[1].text)
def test_saleschannel_disabled(self):
self.event.all_sales_channels = False
self.event.save()
response = self.client.get('/%s/%s/widget/product_list' % (self.orga.slug, self.event.slug))
data = json.loads(response.content.decode())
assert data == {
"error": "Tickets for this event cannot be purchased on this sales channel.",
'poweredby': '<a href="https://pretix.eu" target="_blank" rel="noopener">ticketing powered by pretix</a>',
}
self.assertEqual(response.status_code, 200)
response = self.client.post('/%s/%s/w/aaaaaaaaaaaaaaab/cart/add' % (self.orga.slug, self.event.slug), {
'item_%d' % self.ticket.id: '1'
}, follow=True)
self.assertEqual(response.status_code, 404)
def test_product_list_view(self):
response = self.client.get('/%s/%s/widget/product_list' % (self.orga.slug, self.event.slug))
assert response['Access-Control-Allow-Origin'] == '*'
data = json.loads(response.content.decode())
assert data == {
"target_url": "http://example.com/ccc/30c3/",
"subevent": None,
"name": "30C3",
"date_range": f"{self.event.date_from.strftime('%a')}, Dec. 26th, {self.event.date_from.year} 00:00",
"frontpage_text": "",
"location": "",
"currency": "EUR",
"show_variations_expanded": False,
"display_net_prices": False,
"use_native_spinners": False,
"vouchers_exist": False,
"waiting_list_enabled": False,
"error": None,
"has_seating_plan": False,
"has_seating_plan_waitinglist": False,
'poweredby': '<a href="https://pretix.eu" target="_blank" rel="noopener">ticketing powered by pretix</a>',
"items_by_category": [
{
"items": [
{
"current_unavailability_reason": None,
"order_min": None,
"max_price": None,
"price": {"gross": "23.00", "net": "19.33", "tax": "3.67", "name": "", "rate": "19.00", "includes_mixed_tax_rate": False},
"suggested_price": {"gross": "23.00", "net": "19.33", "tax": "3.67", "name": "", "rate": "19.00", "includes_mixed_tax_rate": False},
"picture": None,
"picture_fullsize": None,
"has_variations": 0,
"allow_waitinglist": True,
"mandatory_priced_addons": False,
"description": None,
"min_price": None,
"avail": [100, None],
"variations": [],
"id": self.ticket.pk,
"free_price": False,
"original_price": None,
"name": "Early-bird ticket",
"order_max": 4
},
{
"current_unavailability_reason": None,
"order_min": None,
"max_price": "14.00",
"price": None,
"suggested_price": None,
"picture": None,
"picture_fullsize": None,
"has_variations": 4,
"allow_waitinglist": True,
"mandatory_priced_addons": False,
"description": None,
"min_price": "12.00",
"avail": None,
"variations": [
{
"value": "Red",
"id": self.shirt_red.pk,
'original_price': None,
"price": {"gross": "14.00", "net": "11.76", "tax": "2.24", "name": "",
"rate": "19.00", "includes_mixed_tax_rate": False},
"suggested_price": {"gross": "14.00", "net": "11.76", "tax": "2.24", "name": "",
"rate": "19.00", "includes_mixed_tax_rate": False},
"description": None,
"avail": [100, None],
"order_max": 2,
"current_unavailability_reason": None,
},
{
"value": "Blue",
"id": self.shirt_blue.pk,
'original_price': None,
"price": {"gross": "12.00", "net": "10.08", "tax": "1.92", "name": "",
"rate": "19.00", "includes_mixed_tax_rate": False},
"suggested_price": {"gross": "12.00", "net": "10.08", "tax": "1.92", "name": "",
"rate": "19.00", "includes_mixed_tax_rate": False},
"description": None,
"avail": [100, None],
"order_max": 2,
"current_unavailability_reason": None,
}
],
"id": self.shirt.pk,
"free_price": False,
"original_price": None,
"name": "T-Shirt",
"order_max": None
}
],
"description": None,
"id": self.category.pk,
"name": "Everything"
}
],
"itemnum": 2,
"display_add_to_cart": True,
"cart_exists": False,
"voucher_explanation_text": "",
}
def test_product_list_view_filter(self):
response = self.client.get('/%s/%s/widget/product_list?items=%s' % (self.orga.slug, self.event.slug,
self.ticket.pk))
assert response['Access-Control-Allow-Origin'] == '*'
data = json.loads(response.content.decode())
assert data['items_by_category'] == [
{
"items": [
{
"current_unavailability_reason": None,
"order_min": None,
"max_price": None,
"price": {"gross": "23.00", "net": "19.33", "tax": "3.67", "name": "", "rate": "19.00",
"includes_mixed_tax_rate": False},
"suggested_price": {"gross": "23.00", "net": "19.33", "tax": "3.67", "name": "", "rate": "19.00",
"includes_mixed_tax_rate": False},
"picture": None,
"picture_fullsize": None,
"has_variations": 0,
"allow_waitinglist": True,
"mandatory_priced_addons": False,
"description": None,
"min_price": None,
"avail": [100, None],
"variations": [],
"id": self.ticket.pk,
"free_price": False,
"original_price": None,
"name": "Early-bird ticket",
"order_max": 4
}
],
"description": None,
"id": self.category.pk,
"name": "Everything"
}
]
response = self.client.get('/%s/%s/widget/product_list?categories=0,%s' % (self.orga.slug, self.event.slug,
self.category.pk))
assert response['Access-Control-Allow-Origin'] == '*'
data = json.loads(response.content.decode())
assert len(data['items_by_category']) == 1
response = self.client.get('/%s/%s/widget/product_list?categories=0' % (self.orga.slug, self.event.slug))
assert response['Access-Control-Allow-Origin'] == '*'
data = json.loads(response.content.decode())
assert len(data['items_by_category']) == 0
def test_product_list_view_variation_filter(self):
response = self.client.get('/%s/%s/widget/product_list?variations=%s' % (self.orga.slug, self.event.slug,
self.shirt_red.pk))
assert response['Access-Control-Allow-Origin'] == '*'
data = json.loads(response.content.decode())
assert data['items_by_category'] == [
{
"items": [
{
"current_unavailability_reason": None,
"order_min": None,
"max_price": "14.00",
"price": None,
"suggested_price": None,
"picture": None,
"picture_fullsize": None,
"has_variations": 4,
"allow_waitinglist": True,
"mandatory_priced_addons": False,
"description": None,
"min_price": "12.00",
"avail": None,
"variations": [
{
"value": "Red",
"id": self.shirt_red.pk,
'original_price': None,
"price": {"gross": "14.00", "net": "11.76", "tax": "2.24", "name": "",
"rate": "19.00", "includes_mixed_tax_rate": False},
"suggested_price": {"gross": "14.00", "net": "11.76", "tax": "2.24", "name": "",
"rate": "19.00", "includes_mixed_tax_rate": False},
"description": None,
"avail": [100, None],
"order_max": 2,
"current_unavailability_reason": None,
}
],
"id": self.shirt.pk,
"free_price": False,
"original_price": None,
"name": "T-Shirt",
"order_max": None
}
],
"description": None,
"id": self.category.pk,
"name": "Everything"
}
]
def test_product_list_view_with_voucher(self):
with scopes_disabled():
self.event.vouchers.create(item=self.ticket, code="ABCDE")
response = self.client.get('/%s/%s/widget/product_list?voucher=ABCDE' % (self.orga.slug, self.event.slug))
assert response['Access-Control-Allow-Origin'] == '*'
data = json.loads(response.content.decode())
assert data == {
"target_url": "http://example.com/ccc/30c3/",
"subevent": None,
"name": "30C3",
"date_range": f"{self.event.date_from.strftime('%a')}, Dec. 26th, {self.event.date_from.year} 00:00",
"frontpage_text": "",
"location": "",
"currency": "EUR",
"show_variations_expanded": False,
"display_net_prices": False,
"use_native_spinners": False,
"has_seating_plan": False,
"has_seating_plan_waitinglist": False,
"vouchers_exist": True,
"waiting_list_enabled": False,
"error": None,
'poweredby': '<a href="https://pretix.eu" target="_blank" rel="noopener">ticketing powered by pretix</a>',
"items_by_category": [
{
"items": [
{
"current_unavailability_reason": None,
"order_min": None,
"max_price": None,
"price": {"gross": "23.00", "net": "19.33", "tax": "3.67", "name": "", "rate": "19.00", "includes_mixed_tax_rate": False},
"suggested_price": {"gross": "23.00", "net": "19.33", "tax": "3.67", "name": "", "rate": "19.00", "includes_mixed_tax_rate": False},
"picture": None,
"picture_fullsize": None,
"has_variations": 0,
"allow_waitinglist": True,
"mandatory_priced_addons": False,
"description": None,
"min_price": None,
"avail": [100, None],
"variations": [],
"id": self.ticket.pk,
"free_price": False,
"original_price": None,
"name": "Early-bird ticket",
"order_max": 4
},
],
"description": None,
"id": self.category.pk,
"name": "Everything"
}
],
"itemnum": 1,
"voucher_explanation_text": "",
"display_add_to_cart": True,
"cart_exists": False
}
def test_product_list_view_with_voucher_variation_through_quota(self):
with scopes_disabled():
self.event.vouchers.create(quota=self.quota_shirts, code="ABCDE")
self.quota_shirts.variations.remove(self.shirt_blue)
response = self.client.get('/%s/%s/widget/product_list?voucher=ABCDE' % (self.orga.slug, self.event.slug))
assert response['Access-Control-Allow-Origin'] == '*'
data = json.loads(response.content.decode())
assert data == {
"target_url": "http://example.com/ccc/30c3/",
"subevent": None,
"name": "30C3",
"date_range": f"{self.event.date_from.strftime('%a')}, Dec. 26th, {self.event.date_from.year} 00:00",
"frontpage_text": "",
"location": "",
"currency": "EUR",
"show_variations_expanded": False,
"display_net_prices": False,
"use_native_spinners": False,
"vouchers_exist": True,
"has_seating_plan": False,
"has_seating_plan_waitinglist": False,
"waiting_list_enabled": False,
"error": None,
'poweredby': '<a href="https://pretix.eu" target="_blank" rel="noopener">ticketing powered by pretix</a>',
"items_by_category": [
{
"items": [
{
'id': self.shirt.pk,
'name': 'T-Shirt',
'picture': None,
"picture_fullsize": None,
'description': None,
'has_variations': 2,
"allow_waitinglist": True,
"mandatory_priced_addons": False,
'current_unavailability_reason': None,
'order_min': None,
'order_max': None,
'price': None,
'suggested_price': None,
'min_price': '14.00',
'max_price': '14.00',
'free_price': False,
'avail': None,
'original_price': None,
'variations': [
{
'id': self.shirt_red.pk,
'value': 'Red',
'order_max': 2,
'description': None,
'original_price': None,
'price': {
'gross': '14.00',
'net': '11.76',
'tax': '2.24',
'rate': '19.00',
'name': '',
'includes_mixed_tax_rate': False
},
'suggested_price': {
'gross': '14.00',
'net': '11.76',
'tax': '2.24',
'rate': '19.00',
'name': '',
'includes_mixed_tax_rate': False
},
'avail': [100, None],
'current_unavailability_reason': None,
},
]
}
],
"description": None,
"id": self.category.pk,
"name": "Everything"
}
],
"itemnum": 1,
"display_add_to_cart": True,
"voucher_explanation_text": "",
"cart_exists": False
}
def test_product_list_view_with_voucher_expired(self):
with scopes_disabled():
self.event.vouchers.create(item=self.ticket, code="ABCDE", valid_until=now() - datetime.timedelta(days=1))
response = self.client.get('/%s/%s/widget/product_list?voucher=ABCDE' % (self.orga.slug, self.event.slug))
assert response['Access-Control-Allow-Origin'] == '*'
data = json.loads(response.content.decode())
assert data == {
"target_url": "http://example.com/ccc/30c3/",
"subevent": None,
"name": "30C3",
"date_range": f"{self.event.date_from.strftime('%a')}, Dec. 26th, {self.event.date_from.year} 00:00",
"frontpage_text": "",
"location": "",
"currency": "EUR",
'poweredby': '<a href="https://pretix.eu" target="_blank" rel="noopener">ticketing powered by pretix</a>',
"show_variations_expanded": False,
"display_net_prices": False,
"use_native_spinners": False,
"has_seating_plan": False,
"has_seating_plan_waitinglist": False,
"vouchers_exist": False,
"waiting_list_enabled": False,
"error": "This voucher is expired.",
"items_by_category": [],
"display_add_to_cart": False,
"cart_exists": False,
"voucher_explanation_text": "",
"itemnum": 0,
}
@override_settings(COMPRESS_PRECOMPILERS=settings.COMPRESS_PRECOMPILERS_ORIGINAL)
def test_css_customized(self):
response = self.client.get('/%s/%s/widget/v1.css' % (self.orga.slug, self.event.slug))
c = b"".join(response.streaming_content).decode()
assert '#8E44B3' in c
assert '#33c33c' not in c
assert '#34c34c' not in c
self.orga.settings.primary_color = "#33c33c"
self.orga.cache.clear()
response = self.client.get('/%s/%s/widget/v1.css' % (self.orga.slug, self.event.slug))
c = b"".join(response.streaming_content).decode()
assert '#8E44B3' not in c
assert '#33c33c' in c
assert '#34c34c' not in c
self.event.settings.primary_color = "#34c34c"
self.event.cache.clear()
response = self.client.get('/%s/%s/widget/v1.css' % (self.orga.slug, self.event.slug))
c = b"".join(response.streaming_content).decode()
assert '#8E44B3' not in c
assert '#33c33c' not in c
assert '#34c34c' in c
def test_js_localized(self):
response = self.client.get('/widget/v1.en.js')
c = response.content.decode()
assert '%m/%d/%Y' in c
assert '%d.%m.%Y' not in c
response = self.client.get('/widget/v1.de.js')
c = response.content.decode()
assert '%m/%d/%Y' not in c
assert '%d.%m.%Y' in c
def test_product_list_view_with_bundle_sold_out(self):
self.quota_shirts.size = 0
self.quota_shirts.save()
self.ticket.bundles.create(bundled_item=self.shirt, bundled_variation=self.shirt_blue,
designated_price=2, count=1)
response = self.client.get('/%s/%s/widget/product_list' % (self.orga.slug, self.event.slug))
assert response['Access-Control-Allow-Origin'] == '*'
data = json.loads(response.content.decode())
assert data["items_by_category"][0]["items"][0]["avail"] == [0, None]
def test_product_list_view_with_bundle_mixed_tax_rate(self):
with scopes_disabled():
self.tr7 = self.event.tax_rules.create(rate=Decimal('7.00'))
self.shirt.tax_rule = self.tr7
self.shirt.require_bundling = True
self.shirt.save()
self.ticket.bundles.create(bundled_item=self.shirt, bundled_variation=self.shirt_blue,
designated_price=2, count=1)
response = self.client.get('/%s/%s/widget/product_list' % (self.orga.slug, self.event.slug))
assert response['Access-Control-Allow-Origin'] == '*'
data = json.loads(response.content.decode())
assert len(data["items_by_category"][0]["items"]) == 1
assert data["items_by_category"][0]["items"][0]["price"] == {
"gross": "23.00",
"net": "19.52",
"tax": "3.48",
"name": "MIXED!",
"rate": "19.00",
"includes_mixed_tax_rate": True
}
def test_subevent_list(self):
self.event.has_subevents = True
self.event.settings.timezone = 'Europe/Berlin'
self.event.save()
with freeze_time("2019-01-01 10:00:00"):
with scopes_disabled():
self.event.subevents.create(name="Past", active=True, date_from=now() - datetime.timedelta(days=3))
se1 = self.event.subevents.create(name="Present", active=True, date_from=now())
se2 = self.event.subevents.create(name="Future", active=True, date_from=now() + datetime.timedelta(days=3))
self.event.subevents.create(name="Disabled", active=False, date_from=now() + datetime.timedelta(days=3))
self.event.subevents.create(name="Hidden", active=True, is_public=False, date_from=now() + datetime.timedelta(days=3))
response = self.client.get('/%s/%s/widget/product_list' % (self.orga.slug, self.event.slug))
data = json.loads(response.content.decode())
assert data == {
'list_type': 'list',
'meta_filter_fields': [],
'name': '30C3',
'frontpage_text': '',
'poweredby': '<a href="https://pretix.eu" target="_blank" rel="noopener">ticketing powered by pretix</a>',
'has_more_events': False,
'events': [
{'name': 'Present', 'date_range': 'Tue, Jan. 1st, 2019 11:00', 'availability': {'color': 'none', 'text': 'More info', 'reason': 'unknown'},
'event_url': 'http://example.com/ccc/30c3/', 'subevent': se1.pk, 'location': ''},
{'name': 'Future', 'date_range': 'Fri, Jan. 4th, 2019 11:00', 'availability': {'color': 'none', 'text': 'More info', 'reason': 'unknown'},
'event_url': 'http://example.com/ccc/30c3/', 'subevent': se2.pk, 'location': ''}
]
}
def test_subevent_calendar(self):
self.event.has_subevents = True
self.event.settings.timezone = 'Europe/Berlin'
self.event.save()
with freeze_time("2019-01-01 10:00:00"):
with scopes_disabled():
self.event.subevents.create(name="Past", active=True, date_from=now() - datetime.timedelta(days=3))
se1 = self.event.subevents.create(name="Present", active=True, date_from=now())
se2 = self.event.subevents.create(name="Future", active=True, date_from=now() + datetime.timedelta(days=3))
self.event.subevents.create(name="Disabled", active=False, date_from=now() + datetime.timedelta(days=3))
self.event.subevents.create(name="Hidden", active=True, is_public=False, date_from=now() + datetime.timedelta(days=3))
response = self.client.get('/%s/%s/widget/product_list?style=calendar' % (self.orga.slug, self.event.slug))
data = json.loads(response.content.decode())
assert data == {
'list_type': 'calendar',
'meta_filter_fields': [],
'date': '2019-01-01',
'name': '30C3',
'frontpage_text': '',
'poweredby': '<a href="https://pretix.eu" target="_blank" rel="noopener">ticketing powered by pretix</a>',
'weeks': [
[
None,
{'day': 1, 'date': '2019-01-01', 'events': [
{'name': 'Present', 'time': '11:00', 'continued': False, 'date_range': 'Tue, Jan. 1st, 2019 11:00',
'location': '',
'availability': {'color': 'none', 'text': 'More info', 'reason': 'unknown'},
'event_url': 'http://example.com/ccc/30c3/', 'subevent': se1.pk}]},
{'day': 2, 'date': '2019-01-02', 'events': []},
{'day': 3, 'date': '2019-01-03', 'events': []},
{'day': 4, 'date': '2019-01-04', 'events': [
{'name': 'Future', 'time': '11:00', 'continued': False, 'date_range': 'Fri, Jan. 4th, 2019 11:00',
'location': '',
'availability': {'color': 'none', 'text': 'More info', 'reason': 'unknown'},
'event_url': 'http://example.com/ccc/30c3/', 'subevent': se2.pk}]},
{'day': 5, 'date': '2019-01-05', 'events': []},
{'day': 6, 'date': '2019-01-06', 'events': []}
],
[
{'day': 7, 'date': '2019-01-07', 'events': []},
{'day': 8, 'date': '2019-01-08', 'events': []},
{'day': 9, 'date': '2019-01-09', 'events': []},
{'day': 10, 'date': '2019-01-10', 'events': []},
{'day': 11, 'date': '2019-01-11', 'events': []},
{'day': 12, 'date': '2019-01-12', 'events': []},
{'day': 13, 'date': '2019-01-13', 'events': []}
],
[
{'day': 14, 'date': '2019-01-14', 'events': []},
{'day': 15, 'date': '2019-01-15', 'events': []},
{'day': 16, 'date': '2019-01-16', 'events': []},
{'day': 17, 'date': '2019-01-17', 'events': []},
{'day': 18, 'date': '2019-01-18', 'events': []},
{'day': 19, 'date': '2019-01-19', 'events': []},
{'day': 20, 'date': '2019-01-20', 'events': []}
],
[
{'day': 21, 'date': '2019-01-21', 'events': []},
{'day': 22, 'date': '2019-01-22', 'events': []},
{'day': 23, 'date': '2019-01-23', 'events': []},
{'day': 24, 'date': '2019-01-24', 'events': []},
{'day': 25, 'date': '2019-01-25', 'events': []},
{'day': 26, 'date': '2019-01-26', 'events': []},
{'day': 27, 'date': '2019-01-27', 'events': []}
],
[
{'day': 28, 'date': '2019-01-28', 'events': []},
{'day': 29, 'date': '2019-01-29', 'events': []},
{'day': 30, 'date': '2019-01-30', 'events': []},
{'day': 31, 'date': '2019-01-31', 'events': []},
None, None, None
]
]
}
def test_subevent_week_calendar(self):
self.event.has_subevents = True
self.event.settings.timezone = 'Europe/Berlin'
self.event.save()
with freeze_time("2019-01-01 10:00:00"):
with scopes_disabled():
self.event.subevents.create(name="Past", active=True, date_from=now() - datetime.timedelta(days=3))
se1 = self.event.subevents.create(name="Present", active=True, date_from=now())
se2 = self.event.subevents.create(name="Future", active=True, date_from=now() + datetime.timedelta(days=3))
self.event.subevents.create(name="Disabled", active=False, date_from=now() + datetime.timedelta(days=3))
self.event.subevents.create(name="Hidden", active=True, is_public=False, date_from=now() + datetime.timedelta(days=3))
response = self.client.get('/%s/%s/widget/product_list?style=week' % (self.orga.slug, self.event.slug))
data = json.loads(response.content.decode())
assert data == {
'list_type': 'week',
'meta_filter_fields': [],
'name': '30C3',
'frontpage_text': '',
'week': [2019, 1],
'poweredby': '<a href="https://pretix.eu" target="_blank" rel="noopener">ticketing powered by pretix</a>',
'days': [
{'day_formatted': 'Mon, Dec 31st', 'date': '2018-12-31', 'events': [], 'today': False},
{'day_formatted': 'Tue, Jan 1st', 'date': '2019-01-01', 'events': [
{'name': 'Present', 'time': '11:00', 'continued': False, 'date_range': 'Tue, Jan. 1st, 2019 11:00',
'location': '',
'availability': {'color': 'none', 'text': 'More info', 'reason': 'unknown'},
'event_url': 'http://example.com/ccc/30c3/', 'subevent': se1.pk}], 'today': True},
{'day_formatted': 'Wed, Jan 2nd', 'date': '2019-01-02', 'events': [], 'today': False},
{'day_formatted': 'Thu, Jan 3rd', 'date': '2019-01-03', 'events': [], 'today': False},
{'day_formatted': 'Fri, Jan 4th', 'date': '2019-01-04', 'events': [
{'name': 'Future', 'time': '11:00', 'continued': False, 'date_range': 'Fri, Jan. 4th, 2019 11:00',
'location': '',
'availability': {'color': 'none', 'text': 'More info', 'reason': 'unknown'},
'event_url': 'http://example.com/ccc/30c3/', 'subevent': se2.pk}], 'today': False},
{'day_formatted': 'Sat, Jan 5th', 'date': '2019-01-05', 'events': [], 'today': False},
{'day_formatted': 'Sun, Jan 6th', 'date': '2019-01-06', 'events': [], 'today': False}
],
}
def test_event_list(self):
self.event.has_subevents = True
self.event.settings.timezone = 'Europe/Berlin'
self.event.save()
with freeze_time("2019-01-01 10:00:00"):
with scopes_disabled():
self.orga.events.create(name="Past", live=True, is_public=True, slug='past', date_from=now() - datetime.timedelta(days=3))
self.orga.events.create(name="Present", live=True, is_public=True, slug='present', date_from=now())
self.orga.events.create(name="Future", live=True, is_public=True, slug='future', date_from=now() + datetime.timedelta(days=3))
self.orga.events.create(name="Disabled", live=False, is_public=True, slug='disabled', date_from=now() + datetime.timedelta(days=3))
self.orga.events.create(name="Secret", live=True, is_public=False, slug='secret', date_from=now() + datetime.timedelta(days=3))
self.event.subevents.create(name="Past", active=True, date_from=now() - datetime.timedelta(days=3))
self.event.subevents.create(name="Present", active=True, date_from=now())
self.event.subevents.create(name="Future", active=True, date_from=now() + datetime.timedelta(days=3))
self.event.subevents.create(name="Disabled", active=False, date_from=now() + datetime.timedelta(days=3))
self.event.subevents.create(name="Hidden", active=True, is_public=False, date_from=now() + datetime.timedelta(days=3))
response = self.client.get('/%s/widget/product_list' % (self.orga.slug,))
data = json.loads(response.content.decode())
assert data == {
'poweredby': '<a href="https://pretix.eu" target="_blank" rel="noopener">ticketing powered by pretix</a>',
'events': [
{'availability': {'color': 'none', 'text': 'Event series'},
'date_range': 'Jan. 1st 4th, 2019',
'event_url': 'http://example.com/ccc/30c3/',
'location': '',
'name': '30C3'},
{'availability': {'color': 'none', 'text': 'More info', 'reason': 'unknown'},
'date_range': 'Tue, Jan. 1st, 2019 10:00',
'location': '',
'event_url': 'http://example.com/ccc/present/',
'name': 'Present'},
{'availability': {'color': 'none', 'text': 'More info', 'reason': 'unknown'},
'date_range': 'Fri, Jan. 4th, 2019 10:00',
'location': '',
'event_url': 'http://example.com/ccc/future/',
'name': 'Future'}
],
'list_type': 'list',
'meta_filter_fields': [],
}
def test_event_list_filtersets_from_allowed_values(self):
self.event.has_subevents = True
self.event.settings.timezone = 'Europe/Berlin'
self.event.save()
with freeze_time("2019-01-01 10:00:00"):
with scopes_disabled():
self.orga.meta_properties.create(
name="Language",
default="EN",
filter_public=True,
choices=[
{"key": "EN", "label": "English"},
{"key": "DE", "label": "German"},
]
)
response = self.client.get('/%s/widget/product_list' % (self.orga.slug,))
data = json.loads(response.content.decode())
assert data["meta_filter_fields"] == [
{
"choices": [["", ""], ["EN", "English"], ["DE", "German"]],
"key": "attr[Language]",
"label": "Language"
}
]
def test_event_list_filtersets_from_existing_values(self):
self.event.has_subevents = True
self.event.settings.timezone = 'Europe/Berlin'
self.event.save()
with freeze_time("2019-01-01 10:00:00"):
with scopes_disabled():
p = self.orga.meta_properties.create(
name="Language",
default="DE",
filter_public=True,
)
e = self.orga.events.create(name="Future", live=True, is_public=True, slug='future', date_from=now() + datetime.timedelta(days=3))
se = self.event.subevents.create(name="Future", active=True, date_from=now() + datetime.timedelta(days=3))
e.meta_values.create(property=p, value="EN")
se.meta_values.create(property=p, value="DE")
response = self.client.get('/%s/widget/product_list' % (self.orga.slug,))
data = json.loads(response.content.decode())
assert data["meta_filter_fields"] == [
{
"choices": [["", ""], ["DE", "DE"], ["EN", "EN"]],
"key": "attr[Language]",
"label": "Language"
}
]
response = self.client.get('/%s/%s/widget/product_list' % (self.orga.slug, self.event.slug))
data = json.loads(response.content.decode())
assert data["meta_filter_fields"] == [
{
"choices": [["", ""], ["DE", "DE"]],
"key": "attr[Language]",
"label": "Language"
}
]
def test_event_calendar(self):
self.event.has_subevents = True
self.event.settings.timezone = 'Europe/Berlin'
self.event.save()
with freeze_time("2019-01-01 10:00:00"):
with scopes_disabled():
self.orga.events.create(name="Past", live=True, is_public=True, slug='past', date_from=now() - datetime.timedelta(days=3))
self.orga.events.create(name="Present", live=True, is_public=True, slug='present', date_from=now())
self.orga.events.create(name="Future", live=True, is_public=True, slug='future', date_from=now() + datetime.timedelta(days=3))
self.orga.events.create(name="Disabled", live=False, is_public=True, slug='disabled', date_from=now() + datetime.timedelta(days=3))
self.orga.events.create(name="Secret", live=True, is_public=False, slug='secret', date_from=now() + datetime.timedelta(days=3))
self.event.subevents.create(name="Past", active=True, date_from=now() - datetime.timedelta(days=3))
se1 = self.event.subevents.create(name="Present", active=True, date_from=now())
se2 = self.event.subevents.create(name="Future", active=True, date_from=now() + datetime.timedelta(days=3))
self.event.subevents.create(name="Disabled", active=False, date_from=now() + datetime.timedelta(days=3))
self.event.subevents.create(name="Hidden", active=True, is_public=False, date_from=now() + datetime.timedelta(days=3))
response = self.client.get('/%s/widget/product_list?style=calendar' % (self.orga.slug,))
data = json.loads(response.content.decode())
assert data == {
'date': '2019-01-01',
'list_type': 'calendar',
'meta_filter_fields': [],
'poweredby': '<a href="https://pretix.eu" target="_blank" rel="noopener">ticketing powered by pretix</a>',
'weeks': [
[None,
{'date': '2019-01-01',
'day': 1,
'events': [{'availability': {'color': 'none', 'text': 'More info', 'reason': 'unknown'},
'continued': False,
'date_range': 'Tue, Jan. 1st, 2019 10:00',
'event_url': 'http://example.com/ccc/present/',
'name': 'Present',
'location': '',
'subevent': None,
'time': '10:00'},
{'availability': {'color': 'none', 'text': 'More info', 'reason': 'unknown'},
'continued': False,
'date_range': 'Tue, Jan. 1st, 2019 11:00',
'event_url': 'http://example.com/ccc/30c3/',
'name': 'Present',
'location': '',
'subevent': se1.pk,
'time': '11:00'}]},
{'date': '2019-01-02', 'day': 2, 'events': []},
{'date': '2019-01-03', 'day': 3, 'events': []},
{'date': '2019-01-04',
'day': 4,
'events': [{'availability': {'color': 'none', 'text': 'More info', 'reason': 'unknown'},
'continued': False,
'date_range': 'Fri, Jan. 4th, 2019 10:00',
'event_url': 'http://example.com/ccc/future/',
'name': 'Future',
'location': '',
'subevent': None,
'time': '10:00'},
{'availability': {'color': 'none', 'text': 'More info', 'reason': 'unknown'},
'continued': False,
'date_range': 'Fri, Jan. 4th, 2019 11:00',
'event_url': 'http://example.com/ccc/30c3/',
'name': 'Future',
'location': '',
'subevent': se2.pk,
'time': '11:00'}]},
{'date': '2019-01-05', 'day': 5, 'events': []},
{'date': '2019-01-06', 'day': 6, 'events': []}],
[{'date': '2019-01-07', 'day': 7, 'events': []},
{'date': '2019-01-08', 'day': 8, 'events': []},
{'date': '2019-01-09', 'day': 9, 'events': []},
{'date': '2019-01-10', 'day': 10, 'events': []},
{'date': '2019-01-11', 'day': 11, 'events': []},
{'date': '2019-01-12', 'day': 12, 'events': []},
{'date': '2019-01-13', 'day': 13, 'events': []}],
[{'date': '2019-01-14', 'day': 14, 'events': []},
{'date': '2019-01-15', 'day': 15, 'events': []},
{'date': '2019-01-16', 'day': 16, 'events': []},
{'date': '2019-01-17', 'day': 17, 'events': []},
{'date': '2019-01-18', 'day': 18, 'events': []},
{'date': '2019-01-19', 'day': 19, 'events': []},
{'date': '2019-01-20', 'day': 20, 'events': []}],
[{'date': '2019-01-21', 'day': 21, 'events': []},
{'date': '2019-01-22', 'day': 22, 'events': []},
{'date': '2019-01-23', 'day': 23, 'events': []},
{'date': '2019-01-24', 'day': 24, 'events': []},
{'date': '2019-01-25', 'day': 25, 'events': []},
{'date': '2019-01-26', 'day': 26, 'events': []},
{'date': '2019-01-27', 'day': 27, 'events': []}],
[{'date': '2019-01-28', 'day': 28, 'events': []},
{'date': '2019-01-29', 'day': 29, 'events': []},
{'date': '2019-01-30', 'day': 30, 'events': []},
{'date': '2019-01-31', 'day': 31, 'events': []},
None,
None,
None]
]
}