Enable jinja2 strict mode in unit tests

This commit is contained in:
Éloi Rivard 2023-07-01 19:56:13 +02:00
parent f7007544ec
commit 1a0a8096eb
8 changed files with 75 additions and 120 deletions

View file

@ -55,6 +55,9 @@ def test_html(user):
site_name=current_app.config.get("NAME", "Canaille"), site_name=current_app.config.get("NAME", "Canaille"),
site_url=base_url, site_url=base_url,
logo=current_app.config.get("LOGO"), logo=current_app.config.get("LOGO"),
title=_("Test email from {website_name}").format(
website_name=current_app.config.get("NAME", "Canaille"),
),
) )
@ -77,6 +80,9 @@ def password_init_html(user):
"account.reset", "account.reset",
user=user, user=user,
hash=profile_hash(user.identifier, user.preferred_email, user.password[0]), hash=profile_hash(user.identifier, user.preferred_email, user.password[0]),
title=_("Password initialization on {website_name}").format(
website_name=current_app.config.get("NAME", "Canaille")
),
_external=True, _external=True,
) )
@ -87,7 +93,7 @@ def password_init_html(user):
reset_url=reset_url, reset_url=reset_url,
logo=current_app.config.get("LOGO"), logo=current_app.config.get("LOGO"),
title=_("Password initialization on {website_name}").format( title=_("Password initialization on {website_name}").format(
website_name=current_app.config.get("NAME", reset_url) website_name=current_app.config.get("NAME", "Canaille")
), ),
) )
@ -105,7 +111,7 @@ def password_init_txt(user):
return render_template( return render_template(
"mail/firstlogin.txt", "mail/firstlogin.txt",
site_name=current_app.config.get("NAME", reset_url), site_name=current_app.config.get("NAME", "Canaille"),
site_url=current_app.config.get("SERVER_NAME", base_url), site_url=current_app.config.get("SERVER_NAME", base_url),
reset_url=reset_url, reset_url=reset_url,
) )
@ -119,6 +125,9 @@ def password_reset_html(user):
"account.reset", "account.reset",
user=user, user=user,
hash=profile_hash(user.identifier, user.preferred_email, user.password[0]), hash=profile_hash(user.identifier, user.preferred_email, user.password[0]),
title=_("Password reset on {website_name}").format(
website_name=current_app.config.get("NAME", "")
),
_external=True, _external=True,
) )
@ -129,7 +138,7 @@ def password_reset_html(user):
reset_url=reset_url, reset_url=reset_url,
logo=current_app.config.get("LOGO"), logo=current_app.config.get("LOGO"),
title=_("Password reset on {website_name}").format( title=_("Password reset on {website_name}").format(
website_name=current_app.config.get("NAME", reset_url) website_name=current_app.config.get("NAME", base_url)
), ),
) )

View file

@ -24,6 +24,7 @@ def send_test_mail(email):
site_name=current_app.config.get("NAME", "Canaille"), site_name=current_app.config.get("NAME", "Canaille"),
site_url=base_url, site_url=base_url,
logo=f"cid:{logo_cid[1:-1]}" if logo_cid else None, logo=f"cid:{logo_cid[1:-1]}" if logo_cid else None,
title=subject,
) )
return send_email( return send_email(
@ -50,20 +51,21 @@ def send_password_reset_mail(user, mail):
logo_cid, logo_filename, logo_raw = logo() logo_cid, logo_filename, logo_raw = logo()
subject = _("Password reset on {website_name}").format( subject = _("Password reset on {website_name}").format(
website_name=current_app.config.get("NAME", reset_url) website_name=current_app.config.get("NAME", base_url)
) )
text_body = render_template( text_body = render_template(
"mail/reset.txt", "mail/reset.txt",
site_name=current_app.config.get("NAME", reset_url), site_name=current_app.config.get("NAME", base_url),
site_url=base_url, site_url=base_url,
reset_url=reset_url, reset_url=reset_url,
) )
html_body = render_template( html_body = render_template(
"mail/reset.html", "mail/reset.html",
site_name=current_app.config.get("NAME", reset_url), site_name=current_app.config.get("NAME", base_url),
site_url=base_url, site_url=base_url,
reset_url=reset_url, reset_url=reset_url,
logo=f"cid:{logo_cid[1:-1]}" if logo_cid else None, logo=f"cid:{logo_cid[1:-1]}" if logo_cid else None,
title=subject,
) )
return send_email( return send_email(
@ -90,20 +92,21 @@ def send_password_initialization_mail(user, email):
logo_cid, logo_filename, logo_raw = logo() logo_cid, logo_filename, logo_raw = logo()
subject = _("Password initialization on {website_name}").format( subject = _("Password initialization on {website_name}").format(
website_name=current_app.config.get("NAME", reset_url) website_name=current_app.config.get("NAME", base_url)
) )
text_body = render_template( text_body = render_template(
"mail/firstlogin.txt", "mail/firstlogin.txt",
site_name=current_app.config.get("NAME", reset_url), site_name=current_app.config.get("NAME", base_url),
site_url=base_url, site_url=base_url,
reset_url=reset_url, reset_url=reset_url,
) )
html_body = render_template( html_body = render_template(
"mail/firstlogin.html", "mail/firstlogin.html",
site_name=current_app.config.get("NAME", reset_url), site_name=current_app.config.get("NAME", base_url),
site_url=base_url, site_url=base_url,
reset_url=reset_url, reset_url=reset_url,
logo=f"cid:{logo_cid[1:-1]}" if logo_cid else None, logo=f"cid:{logo_cid[1:-1]}" if logo_cid else None,
title=subject,
) )
return send_email( return send_email(
@ -120,20 +123,21 @@ def send_invitation_mail(email, registration_url):
logo_cid, logo_filename, logo_raw = logo() logo_cid, logo_filename, logo_raw = logo()
subject = _("You have been invited to create an account on {website_name}").format( subject = _("You have been invited to create an account on {website_name}").format(
website_name=current_app.config.get("NAME", registration_url) website_name=current_app.config.get("NAME", base_url)
) )
text_body = render_template( text_body = render_template(
"mail/invitation.txt", "mail/invitation.txt",
site_name=current_app.config.get("NAME", registration_url), site_name=current_app.config.get("NAME", base_url),
site_url=base_url, site_url=base_url,
registration_url=registration_url, registration_url=registration_url,
) )
html_body = render_template( html_body = render_template(
"mail/invitation.html", "mail/invitation.html",
site_name=current_app.config.get("NAME", registration_url), site_name=current_app.config.get("NAME", base_url),
site_url=base_url, site_url=base_url,
registration_url=registration_url, registration_url=registration_url,
logo=f"cid:{logo_cid[1:-1]}" if logo_cid else None, logo=f"cid:{logo_cid[1:-1]}" if logo_cid else None,
title=subject,
) )
return send_email( return send_email(

View file

@ -2,7 +2,7 @@
{% block content %} {% block content %}
<div class="ui error icon message"> <div class="ui error icon message">
{% if icon and (debug or (user and user.can_manage_oidc)) %} {% if icon is defined and (debug or (user and user.can_manage_oidc)) %}
<i class="{{ icon }} icon"></i> <i class="{{ icon }} icon"></i>
{% elif error_code == 400 %} {% elif error_code == 400 %}
<i class="question icon"></i> <i class="question icon"></i>

View file

@ -183,12 +183,12 @@ id=none,
csrf=true) -%} csrf=true) -%}
<form method="POST" <form method="POST"
id="{{ id or form.__class__.__name__|lower }}" id="{{ id or form.__class__.__name__|lower }}"
action="{{ action or form.action }}" action="{% if action %}{{ action }}{% elif form.action is defined %}{{ form.action }}{% endif %}"
role="form" role="form"
enctype="multipart/form-data" enctype="multipart/form-data"
class="ui form {{ class_ }}" class="ui form {{ class_ }}"
> >
{% if caller %} {% if caller is defined %}
{% if csrf %} {% if csrf %}
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/> <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
{% endif %} {% endif %}

View file

@ -40,7 +40,7 @@
{{ form.hidden_tag() if form.hidden_tag }} {{ form.hidden_tag() if form.hidden_tag }}
<input type="hidden" name="page" value="{{ page }}"> <input type="hidden" name="page" value="{{ page }}">
<input type="hidden" name="query" value="{{ form.query.data }}"> <input type="hidden" name="query" value="{{ form.query.data }}">
{% if page == null %} {% if page is none %}
<span class="icon disabled ui button" style="border-radius: 0"> <span class="icon disabled ui button" style="border-radius: 0">
{{ caller() }} {{ caller() }}
</span> </span>
@ -69,7 +69,7 @@
<i class="left chevron icon"></i> <i class="left chevron icon"></i>
{% endcall %} {% endcall %}
{% else %} {% else %}
{% call buttonform(form, "previous", null) %} {% call buttonform(form, "previous", none) %}
<i class="left chevron icon"></i> <i class="left chevron icon"></i>
{% endcall %} {% endcall %}
{% endif %} {% endif %}
@ -79,7 +79,7 @@
{% endcall %} {% endcall %}
{% endif %} {% endif %}
{% if form.page.data > 2 %} {% if form.page.data > 2 %}
{% call buttonform(form, "ellipsis-previous", null) %} {% call buttonform(form, "ellipsis-previous", none) %}
{% endcall %} {% endcall %}
{% endif %} {% endif %}
@ -87,7 +87,7 @@
{{ form.page.data }} {{ form.page.data }}
</span> </span>
{% if form.page.data < form.page_max - 1 %} {% if form.page.data < form.page_max - 1 %}
{% call buttonform(form, "ellipsis-next", null) %} {% call buttonform(form, "ellipsis-next", none) %}
{% endcall %} {% endcall %}
{% endif %} {% endif %}
@ -101,7 +101,7 @@
<i class="right chevron icon"></i> <i class="right chevron icon"></i>
{% endcall %} {% endcall %}
{% else %} {% else %}
{% call buttonform(form, "next", null) %} {% call buttonform(form, "next", none) %}
<i class="right chevron icon"></i> <i class="right chevron icon"></i>
{% endcall %} {% endcall %}
{% endif %} {% endif %}

View file

@ -1,5 +1,6 @@
{% extends theme('base.html') %} {% extends theme('base.html') %}
{% import 'macro/form.html' as fui %} {% import 'macro/form.html' as fui %}
{% import 'partial/profile_field.html' as profile %}
{%- block title -%} {%- block title -%}
{%- trans %}User creation{% endtrans -%} {%- trans %}User creation{% endtrans -%}
@ -28,64 +29,14 @@
</nav> </nav>
{% endblock %} {% endblock %}
{% macro render_field(field, noindicator=false) %}
{% set lock_indicator = field.render_kw and ("readonly" in field.render_kw or "disabled" in field.render_kw) %}
{% if not edited_user %}
{{ fui.render_field(field, **kwargs) }}
{% elif edited_user.user_name == user.user_name or lock_indicator or noindicator %}
{{ fui.render_field(field, **kwargs) }}
{% elif field.name in edited_user.write %}
{{ fui.render_field(field, **kwargs) }}
{% elif field.name in edited_user.read %}
{{ fui.render_field(field, indicator_icon="eye", indicator_text=_("This user cannot edit this field"), **kwargs) }}
{% else %}
{{ fui.render_field(field, indicator_icon="eye slash", indicator_text=_("This user cannot see this field"), **kwargs) }}
{% endif %}
{% endmacro %}
{% block content %} {% block content %}
{% if self_deletion or (user.can_manage_users and edited_user) %}
<div id="modal-delete" class="ui basic modal">
<div class="ui icon header">
<i class="user minus icon"></i>
{% trans %}Account deletion{% endtrans %}
</div>
<div class="content">
<p>
{% if user.user_name != edited_user.user_name %}
{{ _("Are you sure you want to delete this user? This action is unrevokable and all the data about this user will be removed.") }}
{% else %}
{{ _("Are you sure you want to delete your account? This action is unrevokable and all your data will be removed forever.") }}
{% endif %}
</p>
</div>
<div class="actions">
<div class="ui inverted cancel button">{% trans %}Cancel{% endtrans %}</div>
<div class="ui inverted red approve button">{% trans %}Delete{% endtrans %}</div>
</div>
</div>
{% endif %}
<div class="ui clearing segment"> <div class="ui clearing segment">
<h2 class="ui center aligned header"> <h2 class="ui center aligned header">
<div class="content"> <div class="content">
{% if not edited_user %}
{% trans %}User creation{% endtrans %} {% trans %}User creation{% endtrans %}
{% elif user.user_name == edited_user.user_name %}
{% trans %}My profile{% endtrans %}
{% else %}
{% trans %}User profile edition{% endtrans %}
{% endif %}
</div> </div>
<div class="sub header"> <div class="sub header">
{% if not edited_user %}
{% trans %}Create a new user account{% endtrans %} {% trans %}Create a new user account{% endtrans %}
{% elif user.user_name == edited_user.user_name %}
{% trans %}Edit your personal information{% endtrans %}
{% else %}
{% trans %}Edit information about a user{% endtrans %}
{% endif %}
</div> </div>
</h2> </h2>
@ -96,9 +47,8 @@
<div class="ui grid"> <div class="ui grid">
<div class="three wide column"> <div class="three wide column">
{% block photo_field scoped %} {% block photo_field scoped %}
{{ render_field(form.photo, display=false, class="photo-field") }} {{ profile.render_field(form.photo, display=false, class="photo-field") }}
{{ render_field(form.photo_delete, display=false, class="photo-delete-button") }} {{ profile.render_field(form.photo_delete, display=false, class="photo-delete-button") }}
{% set photo = edited_user.photo and edited_user.photo[0] %}
<label <label
class="ui small bordered image photo-content" class="ui small bordered image photo-content"
for="{{ form.photo.id }}" for="{{ form.photo.id }}"
@ -113,8 +63,7 @@
<label <label
class="ui centered photo-placeholder" class="ui centered photo-placeholder"
for="{{ form.photo.id }}" for="{{ form.photo.id }}"
title="{{ _("Click to upload a photo") }}" title="{{ _("Click to upload a photo") }}">
{% if photo %}style="display: none;"{% endif %}>
<i class="massive centered portrait icon"></i> <i class="massive centered portrait icon"></i>
</label> </label>
{% endblock %} {% endblock %}
@ -126,116 +75,107 @@
{% if "given_name" in form or "family_name" in form %} {% if "given_name" in form or "family_name" in form %}
<div class="equal width fields"> <div class="equal width fields">
{% if "given_name" in form %} {% if "given_name" in form %}
{% block given_name_field scoped %}{{ render_field(form.given_name) }}{% endblock %} {% block given_name_field scoped %}{{ profile.render_field(form.given_name) }}{% endblock %}
{% endif %} {% endif %}
{% if "family_name" in form %} {% if "family_name" in form %}
{% block family_name_field scoped %}{{ render_field(form.family_name) }}{% endblock %} {% block family_name_field scoped %}{{ profile.render_field(form.family_name) }}{% endblock %}
{% endif %} {% endif %}
</div> </div>
{% endif %} {% endif %}
{% if "display_name" in form %} {% if "display_name" in form %}
{% block display_name_field scoped %}{{ render_field(form.display_name) }}{% endblock %} {% block display_name_field scoped %}{{ profile.render_field(form.display_name) }}{% endblock %}
{% endif %} {% endif %}
{% if "photo" in form %}</div></div>{% endif %} {% if "photo" in form %}</div></div>{% endif %}
{% if "emails" in form %} {% if "emails" in form %}
{% block emails_field scoped %}{{ render_field(form.emails) }}{% endblock %} {% block emails_field scoped %}{{ profile.render_field(form.emails) }}{% endblock %}
{% endif %} {% endif %}
{% if "phone_numbers" in form %} {% if "phone_numbers" in form %}
{% block phone_numbers_field scoped %}{{ render_field(form.phone_numbers) }}{% endblock %} {% block phone_numbers_field scoped %}{{ profile.render_field(form.phone_numbers) }}{% endblock %}
{% endif %} {% endif %}
{% if "formatted_address" in form %} {% if "formatted_address" in form %}
{% block formatted_address_field scoped %}{{ render_field(form.formatted_address) }}{% endblock %} {% block formatted_address_field scoped %}{{ profile.render_field(form.formatted_address) }}{% endblock %}
{% endif %} {% endif %}
{% if "street" in form %} {% if "street" in form %}
{% block street_field scoped %}{{ render_field(form.street) }}{% endblock %} {% block street_field scoped %}{{ profile.render_field(form.street) }}{% endblock %}
{% endif %} {% endif %}
<div class="equal width fields"> <div class="equal width fields">
{% if "postal_code" in form %} {% if "postal_code" in form %}
{% block postal_code_field scoped %}{{ render_field(form.postal_code) }}{% endblock %} {% block postal_code_field scoped %}{{ profile.render_field(form.postal_code) }}{% endblock %}
{% endif %} {% endif %}
{% if "locality" in form %} {% if "locality" in form %}
{% block locality_field scoped %}{{ render_field(form.locality) }}{% endblock %} {% block locality_field scoped %}{{ profile.render_field(form.locality) }}{% endblock %}
{% endif %} {% endif %}
{% if "region" in form %} {% if "region" in form %}
{% block region_field scoped %}{{ render_field(form.region) }}{% endblock %} {% block region_field scoped %}{{ profile.render_field(form.region) }}{% endblock %}
{% endif %} {% endif %}
</div> </div>
<div class="equal width fields"> <div class="equal width fields">
{% if "department" in form %} {% if "department" in form %}
{% block department_field scoped %}{{ render_field(form.department) }}{% endblock %} {% block department_field scoped %}{{ profile.render_field(form.department) }}{% endblock %}
{% endif %} {% endif %}
{% if "employee_number" in form %} {% if "employee_number" in form %}
{% block employee_number_field scoped %}{{ render_field(form.employee_number) }}{% endblock %} {% block employee_number_field scoped %}{{ profile.render_field(form.employee_number) }}{% endblock %}
{% endif %} {% endif %}
</div> </div>
<div class="equal width fields"> <div class="equal width fields">
{% if "title" in form %} {% if "title" in form %}
{% block title_field scoped %}{{ render_field(form.title) }}{% endblock %} {% block title_field scoped %}{{ profile.render_field(form.title) }}{% endblock %}
{% endif %} {% endif %}
{% if "organization" in form %} {% if "organization" in form %}
{% block organization_field scoped %}{{ render_field(form.organization) }}{% endblock %} {% block organization_field scoped %}{{ profile.render_field(form.organization) }}{% endblock %}
{% endif %} {% endif %}
</div> </div>
{% if "profile_url" in form %} {% if "profile_url" in form %}
{% block profile_uri_field scoped %}{{ render_field(form.profile_url) }}{% endblock %} {% block profile_uri_field scoped %}{{ profile.render_field(form.profile_url) }}{% endblock %}
{% endif %} {% endif %}
{% if "preferred_language" in form %} {% if "preferred_language" in form %}
{% block preferred_language_field scoped %}{{ render_field(form.preferred_language) }}{% endblock %} {% block preferred_language_field scoped %}{{ profile.render_field(form.preferred_language) }}{% endblock %}
{% endif %} {% endif %}
<h4 class="ui dividing header">{% trans %}Account settings{% endtrans %}</h4> <h4 class="ui dividing header">{% trans %}Account settings{% endtrans %}</h4>
{% if "user_name" in form %} {% if "user_name" in form %}
{% block user_name_field scoped %}{{ render_field(form.user_name) }}{% endblock %} {% block user_name_field scoped %}{{ profile.render_field(form.user_name) }}{% endblock %}
{% endif %} {% endif %}
{% if "groups" in form %} {% if "groups" in form %}
{% block groups_field scoped %}{{ render_field(form.groups) }}{% endblock %} {% block groups_field scoped %}{{ profile.render_field(form.groups) }}{% endblock %}
{% endif %} {% endif %}
{% if "password1" in form %} {% if "password1" in form %}
{% block password_field scoped %} {% block password_field scoped %}
<div class="two fields"> <div class="two fields">
{{ render_field(form.password1, noindicator=true) }} {{ profile.render_field(form.password1, noindicator=true) }}
{{ render_field(form.password2, noindicator=true) }} {{ profile.render_field(form.password2, noindicator=true) }}
</div> </div>
{% endblock %} {% endblock %}
{% endif %} {% endif %}
{% if user.can_manage_users %} {% if user and user.can_manage_users %}
<div class="ui message info"> <div class="ui message info">
<div class="header"> <div class="header">
{% trans %}User password is not mandatory{% endtrans %} {% trans %}User password is not mandatory{% endtrans %}
</div> </div>
{% if has_password %}
<p>{% trans %}The user password can be set:{% endtrans %}</p>
<ul class="ui list">
<li>{% trans %}by filling this form;{% endtrans %}</li>
<li>{% trans %}by sending the user a password initialization mail, after the account creation;{% endtrans %}</li>
<li>{% trans %}or simply waiting for the user to sign-in a first time, and then receive a password initialization mail.{% endtrans %}</li>
</ul>
{% else %}
<p> <p>
{% if has_smtp %} {% if has_smtp %}
{% trans %}The user will not be able to authenticate unless the password is set, but they will be able to ask for a password initialization mail.{% endtrans %} {% trans %}The user will not be able to authenticate unless the password is set, but they will be able to ask for a password initialization mail.{% endtrans %}
@ -243,7 +183,6 @@
{% trans %}The user will not be able to authenticate unless the password is set.{% endtrans %} {% trans %}The user will not be able to authenticate unless the password is set.{% endtrans %}
{% endif %} {% endif %}
</p> </p>
{% endif %}
</div> </div>
{% endif %} {% endif %}
@ -255,6 +194,7 @@
</button> </button>
</div> </div>
</div> </div>
{% endcall %} {% endcall %}
</div> </div>
{% endblock %} {% endblock %}

View file

@ -30,35 +30,35 @@
{% endif %} {% endif %}
{% if user.can_edit_self %} {% if user.can_edit_self %}
<a class="item {% if menuitem == "profile" %}active{% endif %}" <a class="item {% if menuitem is defined and menuitem == "profile" %}active{% endif %}"
href="{{ url_for('account.profile_edition', edited_user=user) }}"> href="{{ url_for('account.profile_edition', edited_user=user) }}">
<i class="id card icon"></i> <i class="id card icon"></i>
{% trans %}Profile{% endtrans %} {% trans %}Profile{% endtrans %}
</a> </a>
{% endif %} {% endif %}
{% if user.can_use_oidc %} {% if user.can_use_oidc %}
<a class="item {% if menuitem == "consents" %}active{% endif %}" <a class="item {% if menuitem is defined and menuitem == "consents" %}active{% endif %}"
href="{{ url_for('oidc.consents.consents') }}"> href="{{ url_for('oidc.consents.consents') }}">
<i class="handshake icon"></i> <i class="handshake icon"></i>
{% trans %}Consents{% endtrans %} {% trans %}Consents{% endtrans %}
</a> </a>
{% endif %} {% endif %}
{% if user.can_manage_users %} {% if user.can_manage_users %}
<a class="item {% if menuitem == "users" %}active{% endif %}" <a class="item {% if menuitem is defined and menuitem == "users" %}active{% endif %}"
href="{{ url_for('account.users') }}"> href="{{ url_for('account.users') }}">
<i class="address book icon"></i> <i class="address book icon"></i>
{% trans %}Users{% endtrans %} {% trans %}Users{% endtrans %}
</a> </a>
{% endif %} {% endif %}
{% if user.can_manage_groups %} {% if user.can_manage_groups %}
<a class="item {% if menuitem == "groups" %}active{% endif %}" <a class="item {% if menuitem is defined and menuitem == "groups" %}active{% endif %}"
href="{{ url_for('groups.groups') }}"> href="{{ url_for('groups.groups') }}">
<i class="users icon"></i> <i class="users icon"></i>
{% trans %}Groups{% endtrans %} {% trans %}Groups{% endtrans %}
</a> </a>
{% endif %} {% endif %}
{% if user.can_manage_oidc %} {% if user.can_manage_oidc %}
<a class="item {% if menuitem == "admin" %}active{% endif %}" href="{{ url_for('admin.mail_index') }}"> <a class="item {% if menuitem is defined and menuitem == "admin" %}active{% endif %}" href="{{ url_for('admin.mail_index') }}">
<i class="settings icon"></i> <i class="settings icon"></i>
{% trans %}Admin{% endtrans %} {% trans %}Admin{% endtrans %}
</a> </a>

View file

@ -2,6 +2,7 @@ import pytest
from canaille import create_app from canaille import create_app
from canaille.app import models from canaille.app import models
from flask_webtest import TestApp from flask_webtest import TestApp
from jinja2 import StrictUndefined
from pytest_lazyfixture import lazy_fixture from pytest_lazyfixture import lazy_fixture
from werkzeug.security import gen_salt from werkzeug.security import gen_salt
@ -89,6 +90,7 @@ def app(configuration, backend):
@pytest.fixture @pytest.fixture
def testclient(app): def testclient(app):
app.config["TESTING"] = True app.config["TESTING"] = True
app.jinja_env.undefined = StrictUndefined
with app.app_context(): with app.app_context():
yield TestApp(app) yield TestApp(app)