wip: manager: add template test page in manager (#83352) #214

Closed
yweber wants to merge 4 commits from wip/83352-template-test-page into main
5 changed files with 177 additions and 1 deletions

View File

@ -330,6 +330,12 @@ class PageEditIncludeInNavigationForm(forms.ModelForm):
return self.instance
class PageInspectTemplateTestForm(forms.Form):
django_template = forms.CharField(
widget=forms.Textarea(attrs={'rows': 5, 'cols': 80}), label=_('Django template')
)
class CellVisibilityForm(forms.Form):
visibility = forms.ChoiceField(
label=_('Visibility'),

View File

@ -5,6 +5,7 @@
<button aria-controls="panel-information" aria-selected="true" id="tab-information" role="tab" tabindex="0">{% trans "Information" %}</button>
<button aria-controls="panel-cells" aria-selected="false" id="tab-cells" role="tab" tabindex="-1">{% trans "Cells" %}</button>
<button aria-controls="panel-settings" aria-selected="false" id="tab-settings" role="tab" tabindex="-1">{% trans "Settings" %}</button>
<button aria-controls="panel-test-template" aria-selected="false" id="tab-test-template" role="tab" tabindex="-1">{% trans "Test template" %}</button>
</div>
<div class="pk-tabs--container">
@ -116,6 +117,81 @@
</div>
</div>
<div aria-labelledby="tab-test-template" hidden id="panel-test-template" role="tabpanel" tabindex="0">
<form action="{% url 'combo-manager-page-inspect-test-template' pk=object.pk %}" method="post">
{% csrf_token %}
{{ inspect_form.as_p }}
<button id="page-inspect-test-template-submit" class="submit-button submit">
{% trans "Test template"%}
</button>
</form>
<div>
<h3>{% trans "Available context" %}</h3>
<dl>
<dt><code>page</code></dt>
<dd>{% trans "The page object" %}</dd>
<dt><code>cells</code></dt>
<dd>{% trans "The array of page's cells" %}</dd>
</dl>
</div>
<div hidden id="page-inspect-test-template-div">
<div class="infonotice">
<h3>{% trans "Template result" %}</h3>
<div id="page-inspect-test-template-result"></div>
</div>
<div class="infonotice">
<h3>{% trans "HTML sources" %}</h3>
<pre id="page-inspect-test-template-result-html"></pre>
</div>
</div>
<div class="errornotice" hidden id="page-inspect-test-template-error-div">
<h3>{% trans "Template rendering error" %}</h3>
<div id="page-inspect-test-template-error"></div>
</div>
</div>
</div>
</div>
<script>
document.body.onload = function() {
function ajax_cllbck() {
const res_div = document.getElementById('page-inspect-test-template-div');
const res_result = document.getElementById('page-inspect-test-template-result');
const res_result_html = document.getElementById('page-inspect-test-template-result-html');
const error_div = document.getElementById('page-inspect-test-template-error-div')
const error_reason = document.getElementById('page-inspect-test-template-error')
const result = JSON.parse(this.responseText)
if('error' in result) {
error_reason.innerHTML = result['error'];
res_div.setAttribute('hidden', 'true');
error_div.removeAttribute('hidden');
} else {
res_result.innerHTML = result['result'];
res_result_html.textContent = result['result'];
error_div.setAttribute('hidden', 'true');
res_div.removeAttribute('hidden');
}
}
function submit_btn_click() {
const csrf_token = document.getElementsByName('csrfmiddlewaretoken')[0].value
const django_template = document.getElementsByName('django_template')[0].value
const querystring =
"csrfmiddlewaretoken="+encodeURIComponent(csrf_token)+"&django_template="+encodeURIComponent(django_template);
const xhttp = new XMLHttpRequest();
xhttp.onload = ajax_cllbck
xhttp.open("POST", "{% url 'combo-manager-page-inspect-test-template' pk=object.pk %}", true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send(querystring);
return false;
}
const submit_btn = document.getElementById('page-inspect-test-template-submit')
submit_btn.onclick = submit_btn_click
}
</script>
{% endwith %}

View File

@ -104,6 +104,11 @@ urlpatterns = [
name='combo-manager-page-edit-roles',
),
re_path(r'^pages/(?P<pk>\d+)/inspect/$', views.page_inspect, name='combo-manager-page-inspect'),
re_path(
r'^pages/(?P<pk>\d+)/inspect/test_template$',
views.page_inspect_test_template,
name='combo-manager-page-inspect-test-template',
),
re_path(r'^pages/(?P<pk>\d+)/history$', views.page_history, name='combo-manager-page-history'),
re_path(
r'^pages/(?P<page_pk>\d+)/history/(?P<pk>\d+)/$',

View File

@ -40,7 +40,8 @@ from django.http import (
JsonResponse,
)
from django.shortcuts import get_object_or_404, redirect, render
from django.template import engines, loader
from django.template import Context, Template, engines, loader
from django.template.exceptions import TemplateSyntaxError
from django.urls import reverse, reverse_lazy
from django.utils.encoding import force_bytes, force_str
from django.utils.formats import date_format
@ -91,6 +92,7 @@ from .forms import (
PageEditSlugForm,
PageEditTitleForm,
PageExportForm,
PageInspectTemplateTestForm,
PageRestrictedAddForm,
PageSelectTemplateForm,
PageSnapshotSaveForm,
@ -659,12 +661,37 @@ class PageInspectView(ManagedPageMixin, DetailView):
prefetch_groups=True,
cells_exclude=Q(placeholder__in=['_auto_tile', '_dashboard', '_suggested_tile']),
)
kwargs['inspect_form'] = PageInspectTemplateTestForm()
return super().get_context_data(**kwargs)
page_inspect = PageInspectView.as_view()
class PageInspectTestTemplateView(ManagedPageMixin, View):
model = Page
def post(self, request, *args, **kwargs):
if 'django_template' not in request.POST:
return HttpResponseBadRequest()
response = {}
try:
template = Template(request.POST['django_template'])
except TemplateSyntaxError as expt:
response['error'] = str(expt)
return JsonResponse(response)
ctx = {'page': self.page, 'cells': self.page.get_cells()}
response['result'] = template.render(Context(ctx))
Review

il faudrait avoir un RequestContext pour avoir accès aux filtres de requête (|cards:"foobar")

il faudrait avoir un RequestContext pour avoir accès aux filtres de requête (`|cards:"foobar"`)
return JsonResponse(response)
page_inspect_test_template = PageInspectTestTemplateView.as_view()
class PageHistoryView(ManagedPageMixin, ListView):
model = PageSnapshot
template_name = 'combo/page_history.html'

View File

@ -3407,3 +3407,65 @@ def test_manager_inspect_page(settings, app, admin_user):
app = login(app)
resp = app.get('/manage/pages/%s/' % page.id)
resp.click('Inspect')
def test_manager_inspect_test_template(app, admin_user):
"""Testing various template rendering :
- checks page & cells basic attribute access
- checks no double rendering of templates
"""
page_title = 'TestPage'
cell_texts = ['FooBar', 'SecondCell']
page = Page.objects.create(title=page_title, slug='testslug')
for cell_text in cell_texts:
TextCell.objects.create(page=page, text=cell_text, order=1)
app = login(app)
inspect_page = app.get('/manage/pages/%d/inspect/' % page.pk)
form_template = inspect_page.forms[0]
tests = (
('{{page.title}}', page_title),
('{% for cell in cells %}{{cell.text}}\n{% endfor %}', '%s\n' % ('\n'.join(cell_texts))),
('{% templatetag openvariable%}1|add:1{%templatetag closevariable%}', '{{1|add:1}}'),
)
for template, expected_result in tests:
form_template['django_template'] = template
resp = form_template.submit()
assert resp.status_int == 200
result = json.loads(resp.text)
assert 'error' not in result
assert result['result'] == expected_result
def test_manager_inspect_test_template_invalid(app, admin_user):
app = login(app)
page_title = 'TestPage'
page = Page.objects.create(title=page_title, slug='testslug')
invalid_templates = ('{{1|add}}', '{{"foo"|badfilter}}')
for bad_template in invalid_templates:
inspect_page = app.get('/manage/pages/%d/inspect/' % page.pk)
form_template = inspect_page.forms[0]
form_template['django_template'] = bad_template
resp = form_template.submit()
assert resp.status_int == 200
result = json.loads(resp.text)
assert 'result' not in result
assert len(result['error']) > 0
# testing bad form (missing expected field)
inspect_page = app.get('/manage/pages/%d/inspect/' % page.pk)
form_template = inspect_page.forms[0]
csrf = form_template['csrfmiddlewaretoken'].value
resp = app.post(
'/manage/pages/%d/inspect/test_template' % page.pk, {'csrfmiddlewaretoken': csrf}, status=400
)