import datetime
import json
import os
import re
import urllib.parse
from io import StringIO
from unittest import mock
import pytest
from django.conf import settings
from django.contrib.auth.models import Group
from django.core.files import File
from django.db import connection
from django.test import override_settings
from django.test.utils import CaptureQueriesContext
from django.urls import reverse
from django.utils.http import quote
try:
import mellon # pylint: disable=unused-import
except ImportError:
mellon = None
import requests
from combo.apps.assets.models import Asset
from combo.data.models import (
ConfigJsonCell,
FeedCell,
JsonCell,
LinkCell,
LinkListCell,
Page,
ParentContentCell,
Redirect,
SiteSettings,
TextCell,
)
from combo.profile.models import Profile
from .test_manager import login
pytestmark = pytest.mark.django_db
def test_missing_index(app):
Page.objects.all().delete()
resp = app.get('/', status=200)
assert 'Welcome' in resp.text
def test_index(app):
Page.objects.all().delete()
page = Page(title='Home', slug='index', template_name='standard')
page.save()
resp = app.get('/index', status=301)
assert urllib.parse.urlparse(resp.location).path == '/'
resp = app.get('/', status=200)
# check {% now %} inside a skeleton_extra_placeholder is interpreted
assert str(datetime.datetime.now().year) in resp.text
def test_page_contents(app):
Page.objects.all().delete()
page = Page(title='Home', slug='index', template_name='standard')
page.save()
cell = TextCell(page=page, placeholder='content', text='Foobar', order=0)
cell.save()
resp = app.get('/', status=200)
assert 'Foobar' in resp.text
def test_page_contents_unlogged_only(app, admin_user):
Page.objects.all().delete()
page = Page(title='Home', slug='index', template_name='standard')
page.save()
cell = TextCell(page=page, placeholder='content', text='Foobar', order=0, restricted_to_unlogged=True)
cell.save()
resp = app.get('/', status=200)
assert 'Foobar' in resp.text
app = login(app)
resp = app.get('/', status=200)
assert not 'Foobar' in resp.text
@pytest.mark.skipif('mellon is None')
def test_mellon_login(app):
with mock.patch('combo.public.views.get_idps') as get_idps:
get_idps.return_value = ['xxx']
resp = app.get('/login/')
assert urllib.parse.urlparse(resp.location).path == '/accounts/mellon/login/'
resp = app.get('/login/?next=whatever')
assert urllib.parse.urlparse(resp.location).query == 'next=whatever'
def test_page_contents_group_presence(app, normal_user):
group = Group(name='plop')
group.save()
Page.objects.all().delete()
page = Page(title='Home', slug='index', template_name='standard')
page.save()
cell = TextCell(page=page, placeholder='content', text='Foobar', order=0, public=False)
cell.save()
cell.groups.set([group])
resp = app.get('/', status=200)
assert 'Foobar' not in resp.text
app = login(app, username='normal-user', password='normal-user')
resp = app.get('/', status=200)
assert 'Foobar' not in resp.text
normal_user.groups.set([group])
resp = app.get('/', status=200)
assert 'Foobar' in resp.text
def test_page_contents_group_absence(app, normal_user):
group = Group(name='plop')
group.save()
Page.objects.all().delete()
page = Page(title='Home', slug='index', template_name='standard')
page.save()
cell = TextCell(
page=page, placeholder='content', text='Foobar', order=0, public=False, restricted_to_unlogged=True
)
cell.save()
cell.groups.set([group])
resp = app.get('/', status=200)
assert 'Foobar' not in resp.text
app = login(app, username='normal-user', password='normal-user')
resp = app.get('/', status=200)
assert 'Foobar' in resp.text
normal_user.groups.set([group])
resp = app.get('/', status=200)
assert 'Foobar' not in resp.text
def test_page_contents_condition(app, normal_user):
page = Page.objects.create(title='Page', slug='page', template_name='standard')
cell1 = TextCell.objects.create(
page=page, placeholder='content', text='Foobar', order=0, condition='True'
)
cell2 = TextCell.objects.create(
page=page, placeholder='content', text='Foobaz', order=1, condition='False'
)
cell3 = LinkListCell.objects.create(order=1, page=page, placeholder='content')
LinkCell.objects.create(
page=page,
placeholder=cell3.link_placeholder,
title='Example Site',
url='http://example.net/',
order=0,
condition='True',
)
LinkCell.objects.create(
page=page,
placeholder=cell3.link_placeholder,
title='Other Site',
url='http://other.net/',
order=1,
condition='False',
)
app = login(app, username='normal-user', password='normal-user')
resp = app.get(page.get_online_url())
assert 'Foobar' in resp.text
assert 'Foobaz' not in resp.text
assert 'Example Site' in resp.text
assert 'Other Site' not in resp.text
page.sub_slug = 'foo_id'
page.save()
cell1.condition = 'foo_id'
cell1.save()
cell2.condition = 'not foo_id'
cell2.save()
resp = app.get(page.get_online_url() + '11/')
assert 'Foobar' in resp.text
assert 'Foobaz' not in resp.text
def test_page_footer_acquisition(app):
Page.objects.all().delete()
page = Page(title='Home', slug='index', template_name='standard')
page.save()
page_index = page
cell = TextCell(page=page, placeholder='footer', text='BARFOO', order=0)
cell.save()
resp = app.get('/', status=200)
assert resp.text.count('BARFOO') == 1
# make sure a parent content cell in the home page doesn't duplicate
# cells
ParentContentCell(page=page, placeholder='footer', order=0).save()
resp = app.get('/', status=200)
assert resp.text.count('BARFOO') == 1
page = Page(title='Second', slug='second', template_name='standard')
page.save()
ParentContentCell(page=page, placeholder='footer', order=0).save()
TextCell(page=page, placeholder='footer', text='BAR2FOO', order=1).save()
resp = app.get('/second', status=301)
assert urllib.parse.urlparse(resp.location).path == '/second/'
with CaptureQueriesContext(connection) as ctx:
resp = app.get('/second/', status=200)
assert resp.text.count('BARFOO') == 1
assert resp.text.count('BAR2FOO') == 1
queries_count_second = len(ctx.captured_queries)
# deeper hierarchy
page3 = Page(title='Third', slug='third', template_name='standard', parent=page)
page3.save()
ParentContentCell(page=page3, placeholder='footer', order=0).save()
page4 = Page(title='Fourth', slug='fourth', template_name='standard', parent=page3)
page4.save()
ParentContentCell(page=page4, placeholder='footer', order=0).save()
page5 = Page(title='Fifth', slug='fifth', template_name='standard', parent=page4)
page5.save()
ParentContentCell(page=page5, placeholder='footer', order=0).save()
# check growth in SQL queries is limited
with CaptureQueriesContext(connection) as ctx:
resp = app.get('/second/third/', status=200)
assert resp.text.count('BARFOO') == 1
assert resp.text.count('BAR2FOO') == 1
queries_count_third = len(ctx.captured_queries)
# +2 for validity info of parent page
assert queries_count_third == queries_count_second + 1
with CaptureQueriesContext(connection) as ctx:
resp = app.get('/second/third/fourth/', status=200)
assert resp.text.count('BARFOO') == 1
assert resp.text.count('BAR2FOO') == 1
queries_count_fourth = len(ctx.captured_queries)
# +1 for get_parents_and_self()
assert queries_count_fourth == queries_count_second + 1 + 1
# check footer doesn't get duplicated in real index children
page6 = Page(title='Sixth', slug='sixth', template_name='standard', parent=page_index)
page6.save()
ParentContentCell(page=page6, placeholder='footer', order=0).save()
resp = app.get('/sixth/', status=200)
assert resp.text.count('BARFOO') == 1
def test_list_of_links_acquisition(app):
Page.objects.all().delete()
index_page = Page(title='Home', slug='index', template_name='standard')
index_page.save()
cell = LinkListCell.objects.create(order=0, page=index_page, placeholder='footer')
LinkCell.objects.create(
page=index_page,
placeholder=cell.link_placeholder,
title='Example Site',
url='http://example.net/',
order=0,
)
LinkCell.objects.create(
page=index_page,
placeholder=cell.link_placeholder,
title='Example2 Site',
url='http://example.org/',
order=1,
)
resp = app.get('/', status=200)
assert resp.text.count('Example Site') == 1
assert resp.text.count('Example2 Site') == 1
page = Page(title='Second', slug='second', template_name='standard')
page.save()
ParentContentCell(page=page, placeholder='footer', order=0).save()
resp = app.get('/second/', status=200)
assert resp.text.count('Example Site') == 1
assert resp.text.count('Example2 Site') == 1
def test_page_redirect(app):
Page.objects.all().delete()
page = Page(
title='Elsewhere', slug='elsewhere', template_name='standard', redirect_url='http://example.net'
)
page.save()
resp = app.get('/elsewhere/', status=302)
assert resp.location == 'http://example.net'
def test_page_templated_redirect(app):
Page.objects.all().delete()
with override_settings(TEMPLATE_VARS={'test_url': 'http://example.net'}):
page = Page(title='Elsewhere', slug='elsewhere', template_name='standard', redirect_url='[test_url]')
page.save()
resp = app.get('/elsewhere/', status=302)
assert resp.location == 'http://example.net'
page.redirect_url = '{{test_url}}/ok'
page.save()
resp = app.get('/elsewhere/', status=302)
assert resp.location == 'http://example.net/ok'
page.redirect_url = '{{unknown_variable}}'
page.save()
resp = app.get('/elsewhere/', status=200)
page.redirect_url = '{% if error %}'
page.save()
resp = app.get('/elsewhere/', status=404)
def test_page_private_unlogged(app):
Page.objects.all().delete()
page = Page(title='Home', slug='index', template_name='standard', public=False)
page.save()
resp = app.get('/', status=302)
assert resp.location.endswith('/login/?next=http%3A//testserver/')
def test_page_private_logged_in(app, admin_user):
Page.objects.all().delete()
page = Page(title='Home', slug='index', template_name='standard', public=False)
page.save()
app = login(app)
app.get('/', status=200)
def test_page_skeleton(app):
Page.objects.all().delete()
page = Page(
title='Elsewhere', slug='elsewhere', template_name='standard', redirect_url='http://example.net/foo/'
)
page.save()
# url prefix match
resp = app.get('/__skeleton__/?source=%s' % quote('http://example.net/foo/bar'))
assert '{% block placeholder-content %}{% block content %}{% endblock %}{% endblock %}' in resp.text
assert '{% block placeholder-footer %}{% block footer %}{% endblock %}{% endblock %}' in resp.text
assert resp.text.startswith('{% with page_template_name="standard" %}\n')
# url netloc match
resp = app.get('/__skeleton__/?source=%s' % quote('http://example.net'))
assert '{% block placeholder-content %}{% block content %}{% endblock %}{% endblock %}' in resp.text
assert '{% block placeholder-footer %}{% block footer %}{% endblock %}{% endblock %}' in resp.text
# settings.KNOWN_SERVICES match
resp = app.get('/__skeleton__/?source=%s' % quote('http://127.0.0.1:8999/'))
assert '{% block placeholder-content %}{% block content %}{% endblock %}{% endblock %}' in resp.text
# no match
resp = app.get('/__skeleton__/?source=%s' % quote('http://example.com/foo/bar'), status=403)
# check with a footer cell
TextCell.objects.create(page=page, placeholder='footer', text='Foobar', order=0)
TextCell.objects.create(page=page, placeholder='content', text='Foobar', slug='unique', order=1)
TextCell.objects.create(page=page, placeholder='content', text='Foobar', slug='dup', order=2)
TextCell.objects.create(page=page, placeholder='content', text='Foobar', slug='dup', order=3)
resp = app.get('/__skeleton__/?source=%s' % quote('http://example.net'))
assert '{% block placeholder-content %}{% block content %}{% endblock %}{% endblock %}' in resp.text
assert '{% block placeholder-footer %}{% block footer %}{% endblock %}{% endblock %}' in resp.text
assert 'Foobar' in resp.text
# check slugs
assert 'id="unique"' in resp.text
assert 'id="dup"' not in resp.text
# check {% now %} inside a skeleton_extra_placeholder is not interpreted
assert '{% now ' in resp.text
assert '{# generation time #}' in resp.text
# check cells in footer are present even if there's no redirection page
page.slug = 'index'
page.save()
resp = app.get('/__skeleton__/?source=%s' % quote('http://127.0.0.1:8999/'))
assert '{% block placeholder-content %}{% block content %}{% endblock %}{% endblock %}' in resp.text
assert '{% block placeholder-footer %}{% block footer %}{% endblock %}{% endblock %}' in resp.text
assert 'Foobar' in resp.text
# check link cells provide a full URL
other_page = Page(title='Plop', slug='plop', template_name='standard')
other_page.save()
cell = LinkCell(page=page, placeholder='footer', link_page=other_page, order=0)
cell.save()
resp = app.get('/__skeleton__/?source=%s' % quote('http://127.0.0.1:8999/'))
assert 'http://testserver/plop' in resp.text
# check images in text cell use full URL
cell = TextCell(page=page, placeholder='footer', order=0)
cell.text = ' vs '
cell.save()
resp = app.get('/__skeleton__/?source=%s' % quote('http://127.0.0.1:8999/'))
assert 'http://testserver/test/foobar.png' in resp.text
# check absolute URIs are not modified
assert 'src="http://www.example.com/test.png"' in resp.text
# check links in text cell use full URL (unless anchors and verbatim)
cell.text = ''' vs
vs'
'''
cell.save()
with override_settings(TEMPLATE_VARS={'test_url': 'http://example.net'}):
resp = app.get('/__skeleton__/?source=%s' % quote('http://127.0.0.1:8999/'))
assert 'href="http://testserver/test/foobar"' in resp.text
assert 'href="http://www.example.com/test"' in resp.text
assert 'href="#top"' in resp.text
assert 'href="http://example.net"' in resp.text
assert 'href="{{ registration_url }}"' in resp.text
# add a bad redirection page (don't use it, do not crash)
page = Page(title='BadRedirection', slug='badredir', template_name='standard', redirect_url='[foo_bar]')
page.save()
resp = app.get('/__skeleton__/?source=%s' % quote('http://example.net/foo/bar'))
resp = app.get('/__skeleton__/?source=%s' % quote('http://example.net/badredir'))
# add a page with restricted visibility
page = Page.objects.create(
title='RestrictedVisibility',
slug='restrictedvisibilit',
template_name='standard',
public=False,
exclude_from_navigation=False,
)
resp = app.get('/__skeleton__/?source=%s' % quote('http://127.0.0.1:8999/'))
assert 'RestrictedVisibility' in resp.text
# check 404 skeleton
resp = app.get('/__skeleton__/?source=404')
assert "This page doesn't exist" in resp.text
assert resp.status_code == 200
assert 'href="http://testserver/test/foobar"' in resp.text
assert 'href="http://www.example.com/test"' in resp.text
assert 'href="#top"' in resp.text
assert 'href="http://testserver/plop/"' in resp.text
# do not consider empty redirection
Page.objects.all().delete()
page = Page(
title='EmptyRedirection', slug='emptyredir', template_name='standard', redirect_url='{{ is_empty }}'
)
page.save()
resp = app.get('/__skeleton__/?source=%s' % quote('http://127.0.0.1:8999/'))
assert resp.headers['x-combo-page-id'] == '__root'
# prefer last match
Page.objects.all().delete()
page = Page(
title='Elsewhere', slug='elsewhere', template_name='standard', redirect_url='http://example.net/foo/'
)
page.save()
cell = TextCell(page=page, placeholder='footer', text='Foobar1', order=0)
cell.save()
page = Page(
title='Elsewhere2',
slug='elsewhere2',
template_name='standard',
redirect_url='http://example.net/foo/',
order=2,
)
page.save()
cell = TextCell(page=page, placeholder='footer', text='Foobar2', order=0)
cell.save()
resp = app.get('/__skeleton__/?source=%s' % quote('http://example.net/foo/bar'))
assert "Foobar2" in resp.text
def test_subpage_location(app):
Page.objects.all().delete()
page_index = Page(title='Home Page', slug='index', template_name='standard')
page_index.save()
page_sibling = Page(title='Second top level page', slug='second', template_name='standard')
page_sibling.save()
page = Page(title='Child of Home', slug='child-home', template_name='standard', parent=page_index)
page.save()
page = Page(title='Grand child of home', slug='grand-child-home', template_name='standard', parent=page)
page.save()
page = Page(title='Child of second', slug='child-second', template_name='standard', parent=page_sibling)
page.save()
page = Page(
title='Grand child of second', slug='grand-child-second', template_name='standard', parent=page
)
page.save()
resp = app.get('/', status=200)
assert 'Home Page' in resp.text
resp = app.get('/child-home/', status=200)
assert 'Child of Home' in resp.text
resp = app.get('/child-home/grand-child-home/', status=200)
assert 'Grand child of home' in resp.text
assert (
urllib.parse.urlparse(app.get('/child-home/grand-child-home', status=301).location).path
== '/child-home/grand-child-home/'
)
app.get('/grand-child-home/', status=404)
resp = app.get('/second/', status=200)
assert 'Second top level page' in resp.text
resp = app.get('/second/child-second/', status=200)
assert 'Child of second' in resp.text
resp = app.get('/second/child-second/grand-child-second/', status=200)
assert 'Grand child of second' in resp.text
def test_repeated_slug(app):
Page.objects.all().delete()
page1 = Page(title='Home Page', slug='index', template_name='standard')
page1.save()
page2 = Page(title='Second top level page', slug='second', template_name='standard')
page2.save()
page3 = Page(title='Child of second', slug='child-second', template_name='standard', parent=page2)
page3.save()
page4 = Page(
title='Grand child of second (named third)', slug='third', template_name='standard', parent=page3
)
page4.save()
page5 = Page(title='Third top level page', slug='third', template_name='standard')
page5.save()
for i, page in enumerate((page1, page2, page3, page4, page5)):
page.order = i
page.save()
resp = app.get('/third/', status=200)
assert 'Third top level page' in resp.text
resp = app.get('/second/child-second/third/', status=200)
assert 'Grand child of second (named third)' in resp.text
# reverse page order, and expect same behaviour
for i, page in enumerate(reversed((page1, page2, page3, page4, page5))):
page.order = i
page.save()
resp = app.get('/third/', status=200)
assert 'Third top level page' in resp.text
resp = app.get('/second/child-second/third/', status=200)
assert 'Grand child of second (named third)' in resp.text
def test_menu(app):
Page.objects.all().delete()
page = Page.objects.create(
title='Page1', slug='index', template_name='standard', exclude_from_navigation=False
)
Page.objects.create(title='Page2', slug='page2', template_name='standard', exclude_from_navigation=False)
Page.objects.create(
title='Page3', slug='page3', template_name='standard', public=False, exclude_from_navigation=False
)
resp = app.get('/', status=200)
assert 'menu-index' in resp.text
assert 'data-menu-page-id="%s"' % page.id
assert 'menu-page2' in resp.text
assert 'menu-page3' in resp.text
def test_404(app):
Page.objects.all().delete()
resp = app.get('/foobar/', status=404)
assert "This page doesn't exist" in resp.text
# check footer cells are taken from homepage
index_page = Page(title='Home', slug='index', template_name='standard')
index_page.save()
cell = TextCell(page=index_page, placeholder='footer', text='FOOBAR', order=0)
cell.save()
resp = app.get('/foobar/', status=404)
assert "This page doesn't exist" in resp.text
assert "FOOBAR" in resp.text
index_page.delete()
# check decidated custom page
page = Page(title='Not Found', slug='404', template_name='standard')
page.save()
TextCell(page=page, placeholder='content', text='Custom 404 Text', order=0).save()
resp = app.get('/foobar/', status=404)
assert 'Custom 404 Text' in resp.text
with override_settings(DEBUG=True):
# check error page provides an hint when debugging
resp = app.get('/foobar/', status=404)
assert "can't find the requested page" in resp.text
# check native django handler is used if all pages are private
page.public = False
page.save()
resp = app.get('/foobar/', status=404)
assert 'Custom 404 Text' not in resp.text
assert "This page doesn't exist" not in resp.text
# check access using its /404/ slug
resp = app.get('/404', status=404)
# check 404 skeleton when all pages are private
resp = app.get('/__skeleton__/?source=404')
assert 'Custom 404 Text' not in resp.text
assert "This page doesn't exist" not in resp.text
assert resp.status_code == 200
def test_style_demo(app, admin_user):
TextCell.objects.all().delete()
Page.objects.all().delete()
app = login(app)
with override_settings(DEBUG=True):
resp = app.get('/__style__/', status=200)
assert 'class="success"' not in resp.text
assert 'class="info"' not in resp.text
assert 'class="warning"' not in resp.text
assert 'class="error"' not in resp.text
assert 'Lorem ipsum' in resp.text
assert TextCell.objects.count() == 0
assert Page.objects.count() == 0
resp = app.get('/__style__/?template=standard-sidebar&with_messages=on', status=200)
assert 'class="success"' in resp.text
assert 'class="info"' in resp.text
assert 'class="warning"' in resp.text
assert 'class="error"' in resp.text
assert 'Lorem ipsum' in resp.text
assert 'links-list' in resp.text
assert Page.objects.count() == 0
def test_page_async_cell(app, nocache):
Page.objects.all().delete()
page = Page(title='Home', slug='index', template_name='standard')
page.save()
cell = FeedCell(page=page, placeholder='content', url='http://example.net', order=1)
cell.save()
resp = app.get('/', status=200)
assert 'data-ajax-cell-must-load="true"' in resp.text
def test_ajax_cell(app):
Page.objects.all().delete()
page = Page(title='Home', slug='index', template_name='standard')
page.save()
page2 = Page(title='Other', slug='other', template_name='standard')
page2.save()
cell = TextCell(page=page, placeholder='content', text='Foobar
', order=0)
cell.save()
resp = app.get(
reverse(
'combo-public-ajax-page-cell', kwargs={'page_pk': page.id, 'cell_reference': cell.get_reference()}
)
)
assert resp.text.strip() == 'Foobar
'
resp = app.get(
reverse(
'combo-public-ajax-page-cell',
kwargs={'page_pk': page2.id, 'cell_reference': cell.get_reference()},
),
status=404,
)
resp = app.get(
reverse(
'combo-public-ajax-page-cell', kwargs={'page_pk': '100', 'cell_reference': cell.get_reference()}
),
status=404,
)
page.public = False
page.save()
resp = app.get(
reverse(
'combo-public-ajax-page-cell', kwargs={'page_pk': page.id, 'cell_reference': cell.get_reference()}
),
status=403,
)
page.public = True
page.save()
cell.public = False
cell.save()
resp = app.get('/', status=200)
assert not 'FOOBAR' in resp.text
resp = app.get(
reverse(
'combo-public-ajax-page-cell', kwargs={'page_pk': page.id, 'cell_reference': cell.get_reference()}
),
status=403,
)
def test_initial_login_page(app, admin_user):
Page.objects.all().delete()
page = Page(title='Home', slug='index', template_name='standard')
page.save()
page = Page(title='Initial Login', slug='initial-login', template_name='standard', public=False)
page.save()
site_settings = SiteSettings.get_singleton()
site_settings.initial_login_page_path = '/initial-login/'
site_settings.save()
resp = app.get('/', status=200)
# first visit
app = login(app)
resp = app.get('/', status=302)
assert urllib.parse.urlparse(resp.location).path == '/initial-login/'
# visit again
resp = app.get('/', status=200)
# delete initial login info
profile = Profile.objects.get(user=admin_user)
profile.initial_login_view_timestamp = None
profile.save(update_fields=['initial_login_view_timestamp'])
with override_settings(
TEMPLATE_VARS={
'portal_url': settings.SITE_BASE_URL,
'idp_url': settings.KNOWN_SERVICES['authentic']['idp']['url'],
}
):
# add templated login page path
site_settings.initial_login_page_path = '{{portal_url}}/foo/'
site_settings.save(update_fields=['initial_login_page_path'])
# "first" visit
app = login(app)
resp = app.get('/', status=302)
assert resp.location == 'http://localhost/foo/'
# delete initial login info, again
profile = Profile.objects.get(user=admin_user)
profile.initial_login_view_timestamp = None
profile.save(update_fields=['initial_login_view_timestamp'])
# add templated login page path to idp url
site_settings.initial_login_page_path = '{{idp_url}}/bar/'
site_settings.save(update_fields=['initial_login_page_path'])
# "first" visit
app = login(app)
resp = app.get('/', status=302)
assert resp.location == 'https://authentic.example.org/bar/'
profile.initial_login_view_timestamp = None
profile.save(update_fields=['initial_login_view_timestamp'])
site_settings.initial_login_page = page
site_settings.save()
# first visit
app = login(app)
resp = app.get('/', status=302)
assert urllib.parse.urlparse(resp.location).path == '/initial-login/'
# visit again
resp = app.get('/', status=200)
def test_welcome_page(app, admin_user):
Page.objects.all().delete()
page = Page(title='Home', slug='index', template_name='standard')
page.save()
page = Page(title='Welcome', slug='welcome', template_name='standard')
page.save()
site_settings = SiteSettings.get_singleton()
site_settings.welcome_page_path = '/welcome/'
site_settings.save()
app.cookiejar.clear()
resp = app.get('/', status=302)
assert urllib.parse.urlparse(resp.location).path == '/welcome/'
resp = app.get('/', status=200)
app.cookiejar.clear()
resp = app.get('/', status=302)
assert urllib.parse.urlparse(resp.location).path == '/welcome/'
app.cookiejar.clear()
app = login(app)
resp = app.get('/', status=200)
with override_settings(
TEMPLATE_VARS={
'portal_url': settings.SITE_BASE_URL,
'idp_url': settings.KNOWN_SERVICES['authentic']['idp']['url'],
}
):
# add templated welcome page path
site_settings.welcome_page_path = '{{portal_url}}/foo/'
site_settings.save(update_fields=['welcome_page_path'])
app.cookiejar.clear()
resp = app.get('/', status=302)
assert resp.location == 'http://localhost/foo/'
# add templated login page path to idp url
site_settings.welcome_page_path = '{{idp_url}}/bar/'
site_settings.save(update_fields=['welcome_page_path'])
app.cookiejar.clear()
resp = app.get('/', status=302)
assert resp.location == 'https://authentic.example.org/bar/'
site_settings.welcome_page = page
site_settings.save()
app.cookiejar.clear()
resp = app.get('/', status=302)
assert urllib.parse.urlparse(resp.location).path == '/welcome/'
resp = app.get('/', status=200)
def test_post_cell(app):
Page.objects.all().delete()
page = Page(title='Home', slug='index', template_name='standard')
page.save()
cell = TextCell(page=page, placeholder='content', text='Foobar
', order=0)
cell.save()
# check it's not possible to post to cell that doesn't have POST support.
resp = app.post(
reverse(
'combo-public-ajax-page-cell', kwargs={'page_pk': page.id, 'cell_reference': cell.get_reference()}
),
params={'hello': 'world'},
status=403,
)
templates_settings = [settings.TEMPLATES[0].copy()]
templates_settings[0]['DIRS'] = ['%s/templates-1' % os.path.abspath(os.path.dirname(__file__))]
with override_settings(
JSON_CELL_TYPES={
'test-post-cell': {
'name': 'Foobar',
'url': 'http://test-post-cell/{{slug}}/',
'form': [
{'label': 'slug', 'varname': 'slug', 'required': True},
],
'actions': {
'create': {
'url': 'http://test-post-cell/{{slug}}/create/',
},
'update': {
'url': 'http://test-post-cell/{{slug}}/update/',
'method': 'PATCH',
},
'search': {
'url': 'http://test-post-cell/{{slug}}/search/',
'method': 'GET',
'response': 'raw',
},
'download': {
'url': 'http://test-post-cell/{{slug}}/download/',
'method': 'GET',
'response': 'raw',
},
},
}
},
TEMPLATES=templates_settings,
):
cell = ConfigJsonCell(page=page, placeholder='content', order=0)
cell.key = 'test-post-cell'
cell.parameters = {'slug': 'slug'}
cell.save()
with mock.patch('combo.utils.requests.get') as requests_get:
requests_get.return_value = mock.Mock(content=json.dumps({'hello': 'world'}), status_code=200)
resp = app.get('/', status=200)
resp.form['value'] = 'plop'
resp.form.fields['items[]'][0].checked = True
with mock.patch('combo.utils.requests.request') as requests_post:
requests_post.return_value = mock.Mock(content=json.dumps({'err': 0}), status_code=200)
resp2 = resp.form.submit()
assert requests_post.call_args[0][0] == 'POST'
assert requests_post.call_args[0][1] == 'http://test-post-cell/slug/create/'
assert requests_post.call_args[1]['json'] == {'value': 'plop', 'items': ['1']}
assert urllib.parse.urlparse(resp2.location).path == '/'
# check ajax call
with mock.patch('combo.utils.requests.request') as requests_post:
requests_post.return_value = mock.Mock(content=json.dumps({'err': 0}), status_code=200)
resp2 = resp.form.submit(headers={'x-requested-with': 'XMLHttpRequest'})
assert requests_post.call_args[0][0] == 'POST'
assert requests_post.call_args[0][1] == 'http://test-post-cell/slug/create/'
assert requests_post.call_args[1]['json'] == {'value': 'plop', 'items': ['1']}
assert resp2.text.startswith('