combo/tests/test_public.py

444 lines
18 KiB
Python

import mock
from webtest import TestApp
import datetime
import json
import pytest
import os
import urllib
from django.conf import settings
from django.core.urlresolvers import reverse
from django.test import override_settings
from combo.wsgi import application
from combo.data.models import (Page, CellBase, TextCell, ParentContentCell,
FeedCell, LinkCell, ConfigJsonCell)
from combo.apps.family.models import FamilyInfosCell
pytestmark = pytest.mark.django_db
from test_manager import admin_user, login
def test_missing_index(app):
Page.objects.all().delete()
resp = app.get('/', status=200)
assert 'Welcome' in resp.body
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 resp.location == 'http://testserver/'
resp = app.get('/', status=200)
# check {% now %} inside a skeleton_extra_placeholder is interpreted
assert str(datetime.datetime.now().year) in resp.body
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.body
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.body
app = login(app)
resp = app.get('/', status=200)
assert not 'Foobar' in resp.body
def test_page_footer_acquisition(app):
Page.objects.all().delete()
page = Page(title='Home', slug='index', template_name='standard')
page.save()
cell = TextCell(page=page, placeholder='footer', text='BARFOO', order=0)
cell.save()
resp = app.get('/', status=200)
assert 'BARFOO' in resp.body
page = Page(title='Second', slug='second', template_name='standard')
page.save()
ParentContentCell(page=page, placeholder='footer', order=0).save()
resp = app.get('/second', status=301)
assert resp.location == 'http://testserver/second/'
resp = app.get('/second/', status=200)
assert 'BARFOO' in resp.body
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'
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 == 'http://testserver/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)
resp = 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' % urllib.quote('http://example.net/foo/bar'))
assert '{% block placeholder-content %}{% block content %}{% endblock %}{% endblock %}' in resp.body
assert '{% block placeholder-footer %}{% block footer %}{% endblock %}{% endblock %}' in resp.body
# url netloc match
resp = app.get('/__skeleton__/?source=%s' % urllib.quote('http://example.net'))
assert '{% block placeholder-content %}{% block content %}{% endblock %}{% endblock %}' in resp.body
assert '{% block placeholder-footer %}{% block footer %}{% endblock %}{% endblock %}' in resp.body
# settings.KNOWN_SERVICES match
resp = app.get('/__skeleton__/?source=%s' % urllib.quote('http://127.0.0.1:8999/'))
assert '{% block placeholder-content %}{% block content %}{% endblock %}{% endblock %}' in resp.body
# no match
resp = app.get('/__skeleton__/?source=%s' % urllib.quote('http://example.com/foo/bar'), status=403)
# check with a footer cell
cell = TextCell(page=page, placeholder='footer', text='Foobar', order=0)
cell.save()
resp = app.get('/__skeleton__/?source=%s' % urllib.quote('http://example.net'))
assert '{% block placeholder-content %}{% block content %}{% endblock %}{% endblock %}' in resp.body
assert not '{% block placeholder-footer %}{% block footer %}{% endblock %}{% endblock %}' in resp.body
assert 'Foobar' in resp.body
# check {% now %} inside a skeleton_extra_placeholder is not interpreted
assert '{%now' in resp.body
# check cells in footer are present even if there's no redirection page
page.slug = 'index'
page.save()
resp = app.get('/__skeleton__/?source=%s' % urllib.quote('http://127.0.0.1:8999/'))
assert '{% block placeholder-content %}{% block content %}{% endblock %}{% endblock %}' in resp.body
assert not '{% block placeholder-footer %}{% block footer %}{% endblock %}{% endblock %}' in resp.body
assert 'Foobar' in resp.body
# 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' % urllib.quote('http://127.0.0.1:8999/'))
assert 'http://testserver/plop' in resp.body
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.body
resp = app.get('/child-home/', status=200)
assert 'Child of Home' in resp.body
resp = app.get('/child-home/grand-child-home/', status=200)
assert 'Grand child of home' in resp.body
assert app.get('/child-home/grand-child-home', status=301).location == \
'http://testserver/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.body
resp = app.get('/second/child-second/', status=200)
assert 'Child of second' in resp.body
resp = app.get('/second/child-second/grand-child-second/', status=200)
assert 'Grand child of second' in resp.body
def test_404(app):
Page.objects.all().delete()
resp = app.get('/foobar/', status=404)
assert "This page doesn't exist" in resp.body
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 'Lorem ipsum' in resp.body
assert TextCell.objects.count() == 0
assert Page.objects.count() == 0
def test_page_async_cell(app):
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.body
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='<p>Foobar</p>', 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.body.strip() == '<p>Foobar</p>'
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.body
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()
with override_settings(COMBO_INITIAL_LOGIN_PAGE_PATH='/initial-login/'):
resp = app.get('/', status=200)
# first visit
app = login(app)
resp = app.get('/', status=302)
assert resp.location == 'http://testserver/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()
with override_settings(COMBO_WELCOME_PAGE_PATH='/welcome/'):
app.cookiejar.clear()
resp = app.get('/', status=302)
assert resp.location == 'http://testserver/welcome/'
resp = app.get('/', status=200)
app.cookiejar.clear()
resp = app.get('/', status=302)
assert resp.location == 'http://testserver/welcome/'
app.cookiejar.clear()
app = login(app)
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='<p>Foobar</p>', 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/',
'actions': {
'create': {
'url': 'http://test-post-cell/create/',
}
}
}},
TEMPLATES=templates_settings
):
cell = ConfigJsonCell(page=page, placeholder='content', order=0)
cell.key = 'test-post-cell'
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'
with mock.patch('combo.utils.requests.post') 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] == 'http://test-post-cell/create/'
assert requests_post.call_args[1]['json'] == {'value': 'plop'}
assert resp2.location == 'http://testserver/'
# check ajax call
with mock.patch('combo.utils.requests.post') 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] == 'http://test-post-cell/create/'
assert requests_post.call_args[1]['json'] == {'value': 'plop'}
assert resp2.content.startswith('<form')
# check error on POST
with mock.patch('combo.utils.requests.post') as requests_post:
requests_post.return_value = mock.Mock(content=json.dumps({'err': 0}), status_code=400)
resp2 = resp.form.submit()
assert resp2.location == 'http://testserver/'
resp2 = resp2.follow()
assert 'Error sending data.' in resp2.content
settings.JSON_CELL_TYPES['test-post-cell']['actions']['create']['error-message'] = 'Failed to create stuff.'
resp2 = resp.form.submit()
assert resp2.location == 'http://testserver/'
resp2 = resp2.follow()
assert 'Failed to create stuff.' in resp2.content
with mock.patch('combo.utils.requests.post') as requests_post:
requests_post.return_value = mock.Mock(content=json.dumps({'err': 0}), status_code=400)
resp2 = resp.form.submit(headers={'x-requested-with': 'XMLHttpRequest'})
assert resp2.content.startswith('<form')
assert resp2.headers['x-error-message'] == 'Failed to create stuff.'
# check variable substitution in URL
with mock.patch('combo.utils.requests.post') as requests_post:
settings.JSON_CELL_TYPES['test-post-cell']['actions']['create'] = {
'url': 'http://test-post-cell/[value]/delete'}
resp2 = resp.form.submit()
assert requests_post.call_args[0][0] == 'http://test-post-cell/plop/delete'
def test_familyinfos_cell_with_placeholders(app, admin_user):
Page.objects.all().delete()
page = Page(title='Family', slug='index', template_name='standard')
page.save()
family_cell = FamilyInfosCell(page=page, placeholder='content', order=0)
family_cell.save()
TextCell(page=page, placeholder='family_unlinked_user', text='<p>Hello anonymous user</p>', order=0,
restricted_to_unlogged=True, public=True).save()
TextCell(page=page, placeholder='family_unlinked_user', text='<p>You are not linked</p>',
order=1, public=False, restricted_to_unlogged=False).save()
resp = app.get(reverse('combo-public-ajax-page-cell',
kwargs={'page_pk': page.pk, 'cell_reference': family_cell.get_reference()}))
assert "<p>Hello anonymous user</p>" in resp.content
assert "<p>You are not linked</p>" not in resp.content
app = login(app)
with override_settings(FAMILY_SERVICE={'root': '/family/'}):
with mock.patch('combo.utils.requests.get') as requests_get:
mocked_response = mock.Mock()
mocked_response.status_code = 200
mocked_response.json.return_value = {'err': 0, 'data': None}
requests_get.return_value = mocked_response
resp = app.get(reverse('combo-public-ajax-page-cell',
kwargs={'page_pk': page.pk, 'cell_reference': family_cell.get_reference()}))
assert "<p>Hello anonymous user</p>" not in resp.content
assert "<p>You are not linked</p>" in resp.content
def test_synchronous_placeholder(app):
page = Page(title=u'foo', slug='foo', template_name='standard', order=0)
page.save()
cell = FeedCell(page=page, placeholder='content', url='http://example.net', order=1)
cell.save()
templates_settings = [settings.TEMPLATES[0].copy()]
templates_settings[0]['DIRS'] = ['%s/templates-1' % os.path.abspath(os.path.dirname(__file__))]
with override_settings(COMBO_PUBLIC_TEMPLATES={
'standard': {
'name': 'Test',
'template': 'combo/page_template_synchronous_placeholder.html',
}},
TEMPLATES=templates_settings
):
with mock.patch('requests.get') as requests_get:
requests_get.return_value = mock.Mock(content='', status_code=200)
resp = app.get('/foo/', status=200)
assert not 'data-ajax-cell-must-load="true"' in resp.body
cell = FeedCell(page=page, placeholder='sidebar', url='http://example.org', order=1)
cell.save()
resp = app.get('/foo/', status=200)
assert resp.body.count('data-ajax-cell-must-load="true"') == 1