Compare commits

..

2 Commits

Author SHA1 Message Date
Raphael Michel
9693625758 Fix failing tests 2025-08-22 09:23:07 +02:00
Raphael Michel
7ecc64ec73 Bump version to 2025.8.0.dev0 2025-08-20 13:04:14 +02:00
17 changed files with 91 additions and 256 deletions

View File

@@ -42,7 +42,7 @@ dependencies = [
"django-filter==25.1",
"django-formset-js-improved==0.5.0.3",
"django-formtools==2.5.1",
"django-hierarkey==2.0.*,>=2.0.1",
"django-hierarkey==2.0.*",
"django-hijack==3.7.*",
"django-i18nfield==1.10.*",
"django-libsass==0.9",

View File

@@ -19,4 +19,4 @@
# 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/>.
#
__version__ = "2025.7.2"
__version__ = "2025.8.0.dev0"

View File

@@ -133,11 +133,11 @@ class TemplateBasedMailRenderer(BaseHTMLMailRenderer):
def template_name(self):
raise NotImplementedError()
def compile_markdown(self, plaintext, context=None):
return markdown_compile_email(plaintext, context=context)
def compile_markdown(self, plaintext):
return markdown_compile_email(plaintext)
def render(self, plain_body: str, plain_signature: str, subject: str, order, position, context) -> str:
body_md = self.compile_markdown(plain_body, context)
body_md = self.compile_markdown(plain_body)
if context:
body_md = format_map(body_md, context=context, mode=SafeFormatter.MODE_RICH_TO_HTML)
htmlctx = {

View File

@@ -222,7 +222,7 @@ def mail(email: Union[str, Sequence[str]], subject: str, template: Union[str, La
'invoice_company': ''
})
renderer = ClassicMailRenderer(None, organizer)
body_plain = render_mail(template, context, placeholder_mode=SafeFormatter.MODE_RICH_TO_PLAIN)
content_plain = body_plain = render_mail(template, context)
subject = str(subject).format_map(TolerantDict(context))
sender = (
sender or
@@ -316,7 +316,6 @@ def mail(email: Union[str, Sequence[str]], subject: str, template: Union[str, La
with override(timezone):
try:
content_plain = render_mail(template, context, placeholder_mode=None)
if plain_text_only:
body_html = None
elif 'context' in inspect.signature(renderer.render).parameters:
@@ -714,11 +713,11 @@ def mail_send(*args, **kwargs):
mail_send_task.apply_async(args=args, kwargs=kwargs)
def render_mail(template, context, placeholder_mode=SafeFormatter.MODE_RICH_TO_PLAIN):
def render_mail(template, context):
if isinstance(template, LazyI18nString):
body = str(template)
if context and placeholder_mode:
body = format_map(body, context, mode=placeholder_mode)
if context:
body = format_map(body, context, mode=SafeFormatter.MODE_IGNORE_RICH)
else:
tpl = get_template(template)
body = tpl.render(context)

View File

@@ -26,7 +26,7 @@ from decimal import Decimal
from django.dispatch import receiver
from django.utils.formats import date_format
from django.utils.html import escape, mark_safe
from django.utils.html import escape
from django.utils.timezone import now
from django.utils.translation import gettext_lazy as _
@@ -123,10 +123,6 @@ class BaseRichTextPlaceholder(BaseTextPlaceholder):
def identifier(self):
return self._identifier
@property
def allowed_in_plain_content(self):
return False
@property
def required_context(self):
return self._args
@@ -198,33 +194,6 @@ class SimpleButtonPlaceholder(BaseRichTextPlaceholder):
return f'{text}: {url}'
class MarkdownTextPlaceholder(BaseRichTextPlaceholder):
def __init__(self, identifier, args, func, sample, inline):
super().__init__(identifier, args)
self._func = func
self._sample = sample
self._snippet = inline
@property
def allowed_in_plain_content(self):
return self._snippet
def render_plain(self, **context):
return self._func(**{k: context[k] for k in self._args})
def render_html(self, **context):
return mark_safe(markdown_compile_email(self.render_plain(**context), snippet=self._snippet))
def render_sample_plain(self, event):
if callable(self._sample):
return self._sample(event)
else:
return self._sample
def render_sample_html(self, event):
return mark_safe(markdown_compile_email(self.render_sample_plain(event), snippet=self._snippet))
class PlaceholderContext(SafeFormatter):
"""
Holds the contextual arguments and corresponding list of available placeholders for formatting
@@ -605,7 +574,7 @@ def base_placeholders(sender, **kwargs):
'invoice_company', ['invoice_address'], lambda invoice_address: invoice_address.company or '',
_('Sample Corporation')
),
MarkdownTextPlaceholder(
SimpleFunctionalTextPlaceholder(
'orders', ['event', 'orders'], lambda event, orders: '\n' + '\n\n'.join(
'* {} - {}'.format(
order.full_code,
@@ -635,7 +604,6 @@ def base_placeholders(sender, **kwargs):
{'code': 'OPKSB', 'secret': '09pjdksflosk3njd', 'hash': 'stuvwxy2z'}
]
),
inline=False,
),
SimpleFunctionalTextPlaceholder(
'hours', ['event', 'waiting_list_entry'], lambda event, waiting_list_entry:
@@ -650,13 +618,12 @@ def base_placeholders(sender, **kwargs):
'code', ['waiting_list_voucher'], lambda waiting_list_voucher: waiting_list_voucher.code,
'68CYU2H6ZTP3WLK5'
),
MarkdownTextPlaceholder(
SimpleFunctionalTextPlaceholder(
# join vouchers with two spaces at end of line so markdown-parser inserts a <br>
'voucher_list', ['voucher_list'], lambda voucher_list: ' \n'.join(voucher_list),
'68CYU2H6ZTP3WLK5 \n7MB94KKPVEPSMVF2',
inline=False,
' 68CYU2H6ZTP3WLK5\n 7MB94KKPVEPSMVF2'
),
MarkdownTextPlaceholder(
SimpleFunctionalTextPlaceholder(
# join vouchers with two spaces at end of line so markdown-parser inserts a <br>
'voucher_url_list', ['event', 'voucher_list'],
lambda event, voucher_list: ' \n'.join([
@@ -671,7 +638,6 @@ def base_placeholders(sender, **kwargs):
) + '?voucher=' + c
for c in ['68CYU2H6ZTP3WLK5', '7MB94KKPVEPSMVF2']
]),
inline=False,
),
SimpleFunctionalTextPlaceholder(
'url', ['event', 'voucher_list'], lambda event, voucher_list: build_absolute_uri(event, 'presale:event.index', kwargs={
@@ -690,13 +656,13 @@ def base_placeholders(sender, **kwargs):
'comment', ['comment'], lambda comment: comment,
_('An individual text with a reason can be inserted here.'),
),
MarkdownTextPlaceholder(
SimpleFunctionalTextPlaceholder(
'payment_info', ['order', 'payments'], _placeholder_payments,
_('The amount has been charged to your card.'), inline=False,
_('The amount has been charged to your card.'),
),
MarkdownTextPlaceholder(
SimpleFunctionalTextPlaceholder(
'payment_info', ['payment_info'], lambda payment_info: payment_info,
_('Please transfer money to this bank account: 9999-9999-9999-9999'), inline=False,
_('Please transfer money to this bank account: 9999-9999-9999-9999'),
),
SimpleFunctionalTextPlaceholder(
'attendee_name', ['position'], lambda position: position.attendee_name,
@@ -753,13 +719,13 @@ def base_placeholders(sender, **kwargs):
))
for k, v in sender.meta_data.items():
ph.append(MarkdownTextPlaceholder(
ph.append(SimpleFunctionalTextPlaceholder(
'meta_%s' % k, ['event'], lambda event, k=k: event.meta_data[k],
v, inline=True,
v
))
ph.append(MarkdownTextPlaceholder(
ph.append(SimpleFunctionalTextPlaceholder(
'meta_%s' % k, ['event_or_subevent'], lambda event_or_subevent, k=k: event_or_subevent.meta_data[k],
v, inline=True,
v
))
return ph
@@ -787,7 +753,7 @@ def get_available_placeholders(event, base_parameters, rich=False):
if not isinstance(val, (list, tuple)):
val = [val]
for v in val:
if isinstance(v, BaseRichTextPlaceholder) and not rich and not v.allowed_in_plain_content:
if isinstance(v, BaseRichTextPlaceholder) and not rich:
continue
if all(rp in base_parameters for rp in v.required_context):
params[v.identifier] = v
@@ -809,13 +775,13 @@ def get_sample_context(event, context_parameters, rich=True):
)
)
elif str(sample).strip().startswith('* ') or str(sample).startswith(' '):
context_dict[k] = mark_safe('<div class="placeholder" title="{}">{}</div>'.format(
context_dict[k] = '<div class="placeholder" title="{}">{}</div>'.format(
lbl,
markdown_compile_email(str(sample))
))
)
else:
context_dict[k] = mark_safe('<span class="placeholder" title="{}">{}</span>'.format(
context_dict[k] = '<span class="placeholder" title="{}">{}</span>'.format(
lbl,
escape(sample)
))
)
return context_dict

View File

@@ -44,7 +44,6 @@ from django.conf import settings
from django.core import signing
from django.urls import reverse
from django.utils.functional import SimpleLazyObject
from django.utils.html import escape
from django.utils.http import url_has_allowed_host_and_scheme
from django.utils.safestring import mark_safe
from markdown import Extension
@@ -53,8 +52,6 @@ from markdown.postprocessors import Postprocessor
from markdown.treeprocessors import UnescapeTreeprocessor
from tlds import tld_set
from pretix.helpers.format import SafeFormatter, format_map
register = template.Library()
ALLOWED_TAGS_SNIPPET = {
@@ -297,44 +294,27 @@ class LinkifyAndCleanExtension(Extension):
)
def markdown_compile_email(source, allowed_tags=None, allowed_attributes=ALLOWED_ATTRIBUTES, snippet=False, context=None):
if allowed_tags is None:
allowed_tags = ALLOWED_TAGS_SNIPPET if snippet else ALLOWED_TAGS
context_callbacks = []
if context:
# This is a workaround to fix placeholders in URL targets
def context_callback(attrs, new=False):
if (None, "href") in attrs and "{" in attrs[None, "href"]:
# Do not use MODE_RICH_TO_HTML to avoid recursive linkification
attrs[None, "href"] = escape(format_map(attrs[None, "href"], context=context, mode=SafeFormatter.MODE_RICH_TO_PLAIN))
return attrs
context_callbacks.append(context_callback)
def markdown_compile_email(source, allowed_tags=ALLOWED_TAGS, allowed_attributes=ALLOWED_ATTRIBUTES):
linker = bleach.Linker(
url_re=URL_RE,
email_re=EMAIL_RE,
callbacks=context_callbacks + DEFAULT_CALLBACKS + [truelink_callback, abslink_callback],
callbacks=DEFAULT_CALLBACKS + [truelink_callback, abslink_callback],
parse_email=True
)
exts = [
'markdown.extensions.sane_lists',
'markdown.extensions.tables',
EmailNl2BrExtension(),
LinkifyAndCleanExtension(
linker,
tags=set(allowed_tags),
attributes=allowed_attributes,
protocols=ALLOWED_PROTOCOLS,
strip=snippet,
)
]
if snippet:
exts.append(SnippetExtension())
return markdown.markdown(
source,
extensions=exts
extensions=[
'markdown.extensions.sane_lists',
'markdown.extensions.tables',
EmailNl2BrExtension(),
LinkifyAndCleanExtension(
linker,
tags=set(allowed_tags),
attributes=allowed_attributes,
protocols=ALLOWED_PROTOCOLS,
strip=False,
)
]
)

View File

@@ -308,8 +308,8 @@ class VoucherBulkForm(VoucherForm):
)
Recipient = namedtuple('Recipient', 'email number name tag')
def _set_field_placeholders(self, fn, base_parameters, rich=False):
placeholders = get_available_placeholders(self.instance.event, base_parameters, rich=rich)
def _set_field_placeholders(self, fn, base_parameters):
placeholders = get_available_placeholders(self.instance.event, base_parameters)
ht = format_placeholders_help_text(placeholders, self.instance.event)
if self.fields[fn].help_text:
@@ -345,7 +345,7 @@ class VoucherBulkForm(VoucherForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._set_field_placeholders('send_subject', ['event', 'name'])
self._set_field_placeholders('send_message', ['event', 'voucher_list', 'name'], rich=True)
self._set_field_placeholders('send_message', ['event', 'voucher_list', 'name'])
with language(self.instance.event.settings.locale, self.instance.event.settings.region):
for f in ("send_subject", "send_message"):

View File

@@ -69,36 +69,34 @@
{% if show_meta %}
<span class="text-muted text-sm">{{ plugin.version }}</span>
{% endif %}
{% if is_active or plugin.level == "event" %}
{% if plugin.level == "organizer" %}
<span class="label label-success" data-is-active>
<span class="fa fa-check" aria-hidden="true"></span>
{% trans "Active" %}
</span>
{% elif events_total and events_counter == events_total %}
<span class="label label-success" data-is-active>
<span class="fa fa-check" aria-hidden="true"></span>
{% trans "Active (all events)" %}
</span>
{% elif events_counter %}
<span class="label label-info" data-is-active>
<span class="fa fa-check" aria-hidden="true"></span>
{% blocktrans trimmed count count=events_counter %}
Active ({{ count }} event)
{% plural %}
Active ({{ count }} events)
{% endblocktrans %}
</span>
{% elif level == "event_organizer" %}
<span class="label label-info" data-is-active>
<span class="fa fa-check" aria-hidden="true"></span>
{% blocktrans trimmed count count=0 %}
Active ({{ count }} event)
{% plural %}
Active ({{ count }} events)
{% endblocktrans %}
</span>
{% endif %}
{% if is_active and level == "organizer" %}
<span class="label label-success" data-is-active>
<span class="fa fa-check" aria-hidden="true"></span>
{% trans "Active" %}
</span>
{% elif events_counter == events_total %}
<span class="label label-success" data-is-active>
<span class="fa fa-check" aria-hidden="true"></span>
{% trans "Active (all events)" %}
</span>
{% elif events_counter %}
<span class="label label-info" data-is-active>
<span class="fa fa-check" aria-hidden="true"></span>
{% blocktrans trimmed count count=events_counter %}
Active ({{ count }} event)
{% plural %}
Active ({{ count }} events)
{% endblocktrans %}
</span>
{% elif level == "event_organizer" %}
<span class="label label-info" data-is-active>
<span class="fa fa-check" aria-hidden="true"></span>
{% blocktrans trimmed count count=0 %}
Active ({{ count }} event)
{% plural %}
Active ({{ count }} events)
{% endblocktrans %}
</span>
{% endif %}
</h4>
{% include "pretixcontrol/event/fragment_plugin_description.html" with plugin=plugin %}

View File

@@ -22,8 +22,6 @@
import logging
from string import Formatter
from django.utils.html import conditional_escape
logger = logging.getLogger(__name__)
@@ -42,10 +40,11 @@ class SafeFormatter(Formatter):
Customized version of ``str.format`` that (a) behaves just like ``str.format_map`` and
(b) does not allow any unwanted shenanigans like attribute access or format specifiers.
"""
MODE_IGNORE_RICH = 0
MODE_RICH_TO_PLAIN = 1
MODE_RICH_TO_HTML = 2
def __init__(self, context, raise_on_missing=False, mode=MODE_RICH_TO_PLAIN):
def __init__(self, context, raise_on_missing=False, mode=MODE_IGNORE_RICH):
self.context = context
self.raise_on_missing = raise_on_missing
self.mode = mode
@@ -56,26 +55,22 @@ class SafeFormatter(Formatter):
def get_value(self, key, args, kwargs):
if not self.raise_on_missing and key not in self.context:
return '{' + str(key) + '}'
return self.context[key]
def _prepare_value(self, value):
if isinstance(value, PlainHtmlAlternativeString):
if self.mode == self.MODE_RICH_TO_PLAIN:
return value.plain
r = self.context[key]
if isinstance(r, PlainHtmlAlternativeString):
if self.mode == self.MODE_IGNORE_RICH:
return '{' + str(key) + '}'
elif self.mode == self.MODE_RICH_TO_PLAIN:
return r.plain
elif self.mode == self.MODE_RICH_TO_HTML:
return value.html
else:
value = str(value)
if self.mode == self.MODE_RICH_TO_HTML:
value = conditional_escape(value)
return value
return r.html
return r
def format_field(self, value, format_spec):
# Ignore format_spec
return super().format_field(self._prepare_value(value), '')
return super().format_field(value, '')
def format_map(template, context, raise_on_missing=False, mode=SafeFormatter.MODE_RICH_TO_PLAIN):
def format_map(template, context, raise_on_missing=False, mode=SafeFormatter.MODE_IGNORE_RICH):
if not isinstance(template, str):
template = str(template)
return SafeFormatter(context, raise_on_missing, mode=mode).format(template)

View File

@@ -33,8 +33,6 @@
# License for the specific language governing permissions and limitations under the License.
import os
import re
from email.mime.text import MIMEText
import pytest
from django.conf import settings
@@ -42,9 +40,7 @@ from django.core import mail as djmail
from django.utils.timezone import now
from django.utils.translation import gettext_lazy as _
from django_scopes import scope
from i18nfield.strings import LazyI18nString
from pretix.base.email import get_email_context
from pretix.base.models import Event, Organizer, User
from pretix.base.services.mail import mail
@@ -52,14 +48,10 @@ from pretix.base.services.mail import mail
@pytest.fixture
def env():
o = Organizer.objects.create(name='Dummy', slug='dummy')
prop1 = o.meta_properties.get_or_create(name="Test")[0]
prop2 = o.meta_properties.get_or_create(name="Website")[0]
event = Event.objects.create(
organizer=o, name='Dummy', slug='dummy',
date_from=now()
)
event.meta_values.update_or_create(property=prop1, defaults={'value': "*Beep*"})
event.meta_values.update_or_create(property=prop2, defaults={'value': "https://example.com"})
user = User.objects.create_user('dummy@dummy.dummy', 'dummy')
user.email = 'dummy@dummy.dummy'
user.save()
@@ -166,95 +158,8 @@ def test_send_mail_with_user_locale(env):
def test_sendmail_placeholder(env):
djmail.outbox = []
event, user, organizer = env
mail('dummy@dummy.dummy', '{event} Test subject', 'mailtest.txt', {"event": event.name}, event)
mail('dummy@dummy.dummy', '{event} Test subject', 'mailtest.txt', {"event": event}, event)
assert len(djmail.outbox) == 1
assert djmail.outbox[0].to == [user.email]
assert djmail.outbox[0].subject == 'Dummy Test subject'
def _extract_html(mail):
for content, mimetype in mail.alternatives:
if "multipart/related" in mimetype:
for sp in content._payload:
if isinstance(sp, MIMEText):
return sp._payload
break
elif "text/html" in mimetype:
return content
@pytest.mark.django_db
def test_placeholder_html_rendering_from_template(env):
djmail.outbox = []
event, user, organizer = env
event.name = "<strong>event & co. kg</strong>"
event.save()
mail('dummy@dummy.dummy', '{event} Test subject', 'mailtest.txt', get_email_context(
event=event,
payment_info="**IBAN**: 123 \n**BIC**: 456",
), event)
assert len(djmail.outbox) == 1
assert djmail.outbox[0].to == [user.email]
assert 'Event name: <strong>event & co. kg</strong>' in djmail.outbox[0].body
assert '**IBAN**: 123 \n**BIC**: 456' in djmail.outbox[0].body
assert '**Meta**: *Beep*' in djmail.outbox[0].body
assert 'Event website: [<strong>event & co. kg</strong>](https://example.org/dummy)' in djmail.outbox[0].body
assert 'Other website: [<strong>event & co. kg</strong>](https://example.com)' in djmail.outbox[0].body
assert '&lt;' not in djmail.outbox[0].body
assert '&amp;' not in djmail.outbox[0].body
html = _extract_html(djmail.outbox[0])
assert '<strong>event' not in html
assert 'Event name: &lt;strong&gt;event &amp; co. kg&lt;/strong&gt;' in html
assert '<strong>IBAN</strong>: 123<br/>\n<strong>BIC</strong>: 456' in html
assert '<strong>Meta</strong>: <em>Beep</em>' in html
assert re.search(
r'Event website: <a href="https://example.org/dummy" rel="noopener" style="[^"]+" target="_blank">&lt;strong&gt;event &amp; co. kg&lt;/strong&gt;</a>',
html
)
assert re.search(
r'Other website: <a href="https://example.com" rel="noopener" style="[^"]+" target="_blank">&lt;strong&gt;event &amp; co. kg&lt;/strong&gt;</a>',
html
)
@pytest.mark.django_db
def test_placeholder_html_rendering_from_string(env):
template = LazyI18nString({
"en": "Event name: {event}\n\nPayment info:\n{payment_info}\n\n**Meta**: {meta_Test}\n\n"
"Event website: [{event}](https://example.org/{event_slug})\n\n"
"Other website: [{event}]({meta_Website})"
})
djmail.outbox = []
event, user, organizer = env
event.name = "<strong>event & co. kg</strong>"
event.save()
mail('dummy@dummy.dummy', '{event} Test subject', template, get_email_context(
event=event,
payment_info="**IBAN**: 123 \n**BIC**: 456",
), event)
assert len(djmail.outbox) == 1
assert djmail.outbox[0].to == [user.email]
assert 'Event name: <strong>event & co. kg</strong>' in djmail.outbox[0].body
assert 'Event website: [<strong>event & co. kg</strong>](https://example.org/dummy)' in djmail.outbox[0].body
assert 'Other website: [<strong>event & co. kg</strong>](https://example.com)' in djmail.outbox[0].body
assert '**IBAN**: 123 \n**BIC**: 456' in djmail.outbox[0].body
assert '**Meta**: *Beep*' in djmail.outbox[0].body
assert '&lt;' not in djmail.outbox[0].body
assert '&amp;' not in djmail.outbox[0].body
html = _extract_html(djmail.outbox[0])
assert '<strong>event' not in html
assert 'Event name: &lt;strong&gt;event &amp; co. kg&lt;/strong&gt;' in html
assert '<strong>IBAN</strong>: 123<br/>\n<strong>BIC</strong>: 456' in html
assert '<strong>Meta</strong>: <em>Beep</em>' in html
assert re.search(
r'Event website: <a href="https://example.org/dummy" rel="noopener" style="[^"]+" target="_blank">&lt;strong&gt;event &amp; co. kg&lt;/strong&gt;</a>',
html
)
assert re.search(
r'Other website: <a href="https://example.com" rel="noopener" style="[^"]+" target="_blank">&lt;strong&gt;event &amp; co. kg&lt;/strong&gt;</a>',
html
)

View File

@@ -40,5 +40,6 @@ def test_format_alternatives():
)
}
assert format_map("Foo {bar}", ctx, mode=SafeFormatter.MODE_IGNORE_RICH) == "Foo {bar}"
assert format_map("Foo {bar}", ctx, mode=SafeFormatter.MODE_RICH_TO_PLAIN) == "Foo plain text"
assert format_map("Foo {bar}", ctx, mode=SafeFormatter.MODE_RICH_TO_HTML) == "Foo <span>HTML version</span>"

View File

@@ -35,7 +35,7 @@ from pretix.plugins.banktransfer.models import BankImportJob, BankTransaction
@pytest.fixture
def env():
o = Organizer.objects.create(name='Dummy', slug='dummy')
o = Organizer.objects.create(name='Dummy', slug='dummy', plugins='pretix.plugins.banktransfer')
event = Event.objects.create(
organizer=o, name='Dummy', slug='dummy',
date_from=now(), plugins='pretix.plugins.banktransfer'

View File

@@ -36,7 +36,7 @@ from pretix.plugins.banktransfer.models import BankImportJob, BankTransaction
@pytest.fixture
def env():
o = Organizer.objects.create(name='Dummy', slug='dummy')
o = Organizer.objects.create(name='Dummy', slug='dummy', plugins='pretix.plugins.banktransfer')
event = Event.objects.create(
organizer=o, name='Dummy', slug='dummy',
date_from=now(), plugins='pretix.plugins.banktransfer'

View File

@@ -53,7 +53,7 @@ from pretix.plugins.banktransfer.tasks import process_banktransfers
@pytest.fixture
def env():
o = Organizer.objects.create(name='Dummy', slug='dummy')
o = Organizer.objects.create(name='Dummy', slug='dummy', plugins='pretix.plugins.banktransfer')
event = Event.objects.create(
organizer=o, name='Dummy', slug='dummy',
date_from=now(), plugins='pretix.plugins.banktransfer,pretix.plugins.paypal'

View File

@@ -34,7 +34,7 @@ from pretix.base.models import (
@pytest.fixture
def env():
o = Organizer.objects.create(name='Dummy', slug='dummy')
o = Organizer.objects.create(name='Dummy', slug='dummy', plugins='pretix.plugins.banktransfer')
event = Event.objects.create(
organizer=o, name='Dummy', slug='dummy',
date_from=now(), plugins='pretix.plugins.banktransfer,pretix.plugins.paypal'

View File

@@ -35,7 +35,7 @@ from pretix.plugins.banktransfer.views import (
@pytest.fixture
def env():
o = Organizer.objects.create(name='Dummy', slug='dummy')
o = Organizer.objects.create(name='Dummy', slug='dummy', plugins='pretix.plugins.banktransfer')
event = Event.objects.create(
organizer=o, name='Dummy', slug='dummy',
date_from=now(), plugins='pretix.plugins.banktransfer,pretix.plugins.paypal'

View File

@@ -1,13 +1,4 @@
{% load i18n %}
This is a test file for sending mails.
Event name: {event}
{% get_current_language as LANGUAGE_CODE %}
The language code used for rendering this email is {{ LANGUAGE_CODE }}.
Payment info:
{payment_info}
**Meta**: {meta_Test}
Event website: [{event}](https://example.org/{event_slug})
Other website: [{event}]({meta_Website})