combo/tests/test_manager.py

886 lines
34 KiB
Python

import base64
import json
import os
import re
import shutil
import StringIO
import urllib
import mock
from django.core.files.storage import default_storage
from django.core.urlresolvers import reverse
from django.conf import settings
from django.contrib.auth.models import User
from django.template import TemplateSyntaxError
from django.test import override_settings
import pytest
from webtest import TestApp
from webtest import Upload
from combo.wsgi import application
from combo.data.models import Page, CellBase, TextCell, LinkCell, ConfigJsonCell, JsonCell, PageSnapshot
from combo.apps.assets.models import Asset
from combo.apps.family.models import FamilyInfosCell
from combo.apps.search.models import SearchCell
pytestmark = pytest.mark.django_db
TESTS_DATA_DIR = os.path.join(os.path.dirname(__file__), 'data')
@pytest.fixture
def admin_user():
try:
user = User.objects.get(username='admin')
except User.DoesNotExist:
user = User.objects.create_superuser('admin', email=None, password='admin')
return user
def login(app, username='admin', password='admin'):
login_page = app.get('/login/')
login_form = login_page.forms[0]
login_form['username'] = username
login_form['password'] = password
resp = login_form.submit()
assert resp.status_int == 302
return app
def test_unlogged_access(app):
# connect while not being logged in
assert app.get('/manage/', status=302).location.endswith('/login/?next=/manage/')
def test_access(app, admin_user):
app = login(app)
resp = app.get('/manage/', status=200)
assert 'Pages' in resp.body
assert "This site doesn't have any page yet." in resp.body
def test_add_page(app, admin_user):
app = login(app)
resp = app.get('/manage/', status=200)
resp = resp.click('New')
assert resp.forms[0]['title'].value == 'Home' # default title for first page
resp = resp.forms[0].submit()
assert resp.location.endswith('/manage/pages/1/')
assert Page.objects.get(slug='index').title == 'Home'
assert Page.objects.get(slug='index').template_name == 'standard' # first one was taken
def test_add_second_page(app, admin_user):
Page.objects.all().delete()
page = Page(title='One', slug='one')
page.save()
app = login(app)
resp = app.get('/manage/', status=200)
resp = resp.click('New')
# assert there's no defaul title for the second page
assert resp.forms[0]['title'].value == ''
resp.forms[0]['title'].value = 'Foobar'
resp = resp.forms[0].submit()
assert Page.objects.get(slug='foobar').title == 'Foobar'
def test_edit_page(app, admin_user):
Page.objects.all().delete()
app = login(app)
resp = app.get('/manage/', status=200)
resp = resp.click('New')
resp = resp.forms[0].submit()
resp = resp.follow()
# title
resp = resp.click(href='.*/title')
resp.form['title'].value = 'Home 2'
resp = resp.form.submit()
resp = resp.follow()
assert Page.objects.all()[0].title == 'Home 2'
# slug
resp = resp.click(href='.*/slug')
resp.form['slug'].value = 'foobar'
resp = resp.form.submit()
resp = resp.follow()
assert Page.objects.all()[0].slug == 'foobar'
# description
resp = resp.click(href='.*/description')
resp.form['description'].value = 'second home page'
resp = resp.form.submit()
resp = resp.follow()
assert Page.objects.all()[0].description == 'second home page'
# template name
resp = resp.click(href='.*/template')
assert resp.form['template_name'].value == 'standard'
assert len(resp.form['template_name'].options) == 2 # by default there are 2 templates
resp.form['template_name'].value = 'standard-sidebar'
resp = resp.form.submit()
resp = resp.follow()
assert Page.objects.all()[0].template_name == 'standard-sidebar'
assert resp.click(href='.*/template').form['template_name'].value == 'standard-sidebar'
# redirection
resp = resp.click(href='.*/redirection')
resp.form['redirect_url'].value = 'http://www.example.net'
resp = resp.form.submit()
resp = resp.follow()
assert 'http://www.example.net' in resp.body
assert Page.objects.all()[0].redirect_url == 'http://www.example.net'
# exclude from nav
resp = resp.click(href='.*/exclude-from-navigation')
resp.form['exclude_from_navigation'].checked = True
resp = resp.form.submit()
resp = resp.follow()
assert Page.objects.all()[0].exclude_from_navigation is True
def test_page_edit_slug(app, admin_user):
Page.objects.all().delete()
page = Page(title='One', slug='one', template_name='standard')
page.save()
page = Page(title='Two', slug='two', template_name='standard')
page.save()
app = login(app)
resp = app.get('/manage/pages/%s/' % page.id)
resp = resp.click(href='.*/slug')
resp.form['slug'].value = 'two' # no change
resp = resp.form.submit()
resp = resp.follow()
assert Page.objects.get(id=page.id).slug == 'two'
resp = resp.click(href='.*/slug')
resp.form['slug'].value = 'two2' # valid change
resp = resp.form.submit()
resp = resp.follow()
assert Page.objects.get(id=page.id).slug == 'two2'
resp = resp.click(href='.*/slug')
resp.form['slug'].value = 'one' # duplicate
resp = resp.form.submit()
assert 'Slug must be unique' in resp.body
assert Page.objects.get(id=page.id).slug == 'two2'
def test_page_edit_picture(app, admin_user):
Page.objects.all().delete()
page = Page(title='One', slug='one', template_name='standard')
page.save()
app = login(app)
resp = app.get('/manage/pages/%s/' % page.id)
resp = resp.click(href='.*/picture/')
resp.form['picture'] = Upload('black.jpeg',
open(os.path.join(TESTS_DATA_DIR, 'black.jpeg')).read(), 'image/jpeg')
resp = resp.form.submit()
assert resp.location.endswith('/manage/pages/%s/' % page.id)
resp = resp.follow()
assert '<h2>Page - One</h2>' in resp.body
assert '<img' in resp.body
resp = resp.click(href='.*/remove-picture/')
resp = resp.follow()
assert '<h2>Page - One</h2>' in resp.body
assert not '<img' in resp.body
def test_delete_page(app, admin_user):
Page.objects.all().delete()
page = Page(title='One', slug='one', template_name='standard')
page.save()
app = login(app)
resp = app.get('/manage/pages/%s/' % page.id)
resp = resp.click('delete')
assert '<button class="delete-button">Delete</button>' in resp.body
resp = resp.forms[0].submit()
assert resp.location.endswith('/manage/')
assert Page.objects.count() == 0
def test_delete_page_keep_child(app, admin_user):
Page.objects.all().delete()
page = Page(title='One', slug='one', template_name='standard')
page.save()
page2 = Page(title='Two', slug='two', parent=page, template_name='standard')
page2.save()
app = login(app)
resp = app.get('/manage/pages/%s/' % page.id)
resp = resp.click('delete')
assert '<button class="delete-button">Delete</button>' in resp.body
assert 'Delete only this page' in resp.body
assert 'Delete this page and all subpages' in resp.body
resp.form['choice'].value = 'delete-one'
resp = resp.forms[0].submit()
assert resp.location.endswith('/manage/')
assert Page.objects.count() == 1
assert Page.objects.get(id=page2.id) == page2
def test_delete_page_and_subpage(app, admin_user):
Page.objects.all().delete()
page = Page(title='One', slug='one', template_name='standard')
page.save()
page2 = Page(title='Two', slug='two', parent=page, template_name='standard')
page2.save()
app = login(app)
resp = app.get('/manage/pages/%s/' % page.id)
resp = resp.click('delete')
assert '<button class="delete-button">Delete</button>' in resp.body
assert 'Delete only this page' in resp.body
assert 'Delete this page and all subpages' in resp.body
resp.form['choice'].value = 'delete-all'
resp = resp.forms[0].submit()
assert resp.location.endswith('/manage/')
assert Page.objects.count() == 0
def test_export_page(app, admin_user):
Page.objects.all().delete()
page = Page(title='One', slug='one', template_name='standard')
page.save()
app = login(app)
resp = app.get('/manage/pages/%s/' % page.id)
resp = resp.click('export')
assert resp.headers['content-type'] == 'application/json'
assert resp.json['pages'][0].get('fields').get('slug') == 'one'
def test_export_page_order():
Page.objects.all().delete()
page1 = Page(title='One', slug='one', template_name='standard')
page2 = Page(title='Two', slug='two', parent=page1, template_name='standard')
page3 = Page(title='Three', slug='three', parent=page2, template_name='standard')
page4 = Page(title='Four', slug='four', parent=page1, template_name='standard')
random_list = [page3, page4, page1, page2]
ordered_list = Page.get_as_reordered_flat_hierarchy(random_list)
assert ordered_list[0] == page1
assert ordered_list[1] == page4
assert ordered_list[2] == page2
assert ordered_list[3] == page3
def test_site_export_import(app, admin_user):
Page.objects.all().delete()
page1 = Page(title='One', slug='one', template_name='standard')
page1.save()
page2 = Page(title='Two', slug='two', parent=page1, template_name='standard')
page2.save()
page3 = Page(title='Three', slug='three', parent=page2, template_name='standard')
page3.save()
page4 = Page(title='Four', slug='four', parent=page1, template_name='standard')
page4.save()
cell = TextCell(page=page1, placeholder='content', text='Foobar', order=0)
cell.save()
cell = LinkCell(page=page1, placeholder='content', link_page=page2, order=0)
cell.save()
cell = LinkCell(page=page2, placeholder='content', link_page=page1, order=0)
cell.save()
app = login(app)
resp = app.get('/manage/')
resp = resp.click('Export Site')
assert resp.headers['content-type'] == 'application/json'
site_export = resp.body
Page.objects.all().delete()
assert LinkCell.objects.count() == 0
app = login(app)
resp = app.get('/manage/')
resp = resp.click('Import Site')
resp.form['site_json'] = Upload('site-export.json', site_export, 'application/json')
resp = resp.form.submit()
assert Page.objects.count() == 4
assert LinkCell.objects.count() == 2
assert LinkCell.objects.get(page__slug='one').link_page.slug == 'two'
assert LinkCell.objects.get(page__slug='two').link_page.slug == 'one'
# check with invalid file
resp = app.get('/manage/')
resp = resp.click('Import Site')
resp.form['site_json'] = Upload('site-export.json', 'invalid content', 'application/json')
resp = resp.form.submit()
assert 'File is not in the expected JSON format.' in resp.body
def test_add_edit_cell(app, admin_user):
Page.objects.all().delete()
page = Page(title='One', slug='one', template_name='standard')
page.save()
app = login(app)
resp = app.get('/manage/pages/%s/' % page.id)
# click on first option link, this should add a text cell
resp = app.get(resp.html.find('option').get('data-add-url'))
assert resp.location.endswith('/manage/pages/1/')
cells = CellBase.get_cells(page_id=page.id)
assert len(cells) == 1
assert isinstance(cells[0], TextCell)
resp = app.get('/manage/pages/%s/' % page.id)
assert ('data-cell-reference="%s"' % cells[0].get_reference()) in resp.body
resp.forms[0]['c%s-text' % cells[0].get_reference()].value = 'Hello world'
resp = resp.forms[0].submit()
assert resp.status_int == 302
assert resp.location.endswith('/manage/pages/1/')
resp = app.get('/manage/pages/%s/' % page.id)
assert resp.forms[0]['c%s-text' % cells[0].get_reference()].value == 'Hello world'
resp = app.get('/manage/pages/%s/' % page.id)
assert ('data-cell-reference="%s"' % cells[0].get_reference()) in resp.body
resp.forms[0]['c%s-text' % cells[0].get_reference()].value = 'World Hello'
resp = resp.forms[0].submit(xhr=True)
assert resp.status_int == 200
assert resp.body.startswith('<p><label')
resp = app.get('/manage/pages/%s/' % page.id)
assert resp.forms[0]['c%s-text' % cells[0].get_reference()].value == 'World Hello'
def test_add_all_basic_cell_types(app, admin_user):
Page.objects.all().delete()
page = Page(title='One', slug='one', template_name='standard')
page.save()
app = login(app)
resp = app.get('/manage/pages/%s/' % page.id)
for option in resp.html.find_all('option'):
if not '/data_' in option.get('data-add-url'):
continue
resp = app.get(option.get('data-add-url'))
resp = resp.follow()
SEARCH_SERVICES = {
'search1': {
'label': 'Search 1',
'url': 'http://www.example.net/search/?q=%(q)s',
}
}
class SearchServices(object):
def __init__(self, search_services):
self.search_services = search_services
def __enter__(self):
settings.COMBO_SEARCH_SERVICES = self.search_services
def __exit__(self, *args, **kwargs):
settings.COMBO_SEARCH_SERVICES = {}
def test_search_cell(app, admin_user):
Page.objects.all().delete()
page = Page(title='One', slug='one', template_name='standard')
page.save()
# add
app = login(app)
assert SearchCell.objects.count() == 0
with SearchServices(SEARCH_SERVICES):
resp = app.get('/manage/pages/%s/' % page.id)
for option in resp.html.find_all('option'):
if 'content/search_' in option.get('data-add-url'):
resp = app.get(option.get('data-add-url'))
resp = resp.follow()
assert SearchCell.objects.count() == 1
cell = SearchCell.objects.first()
# delete
app = login(app)
resp = app.get('/manage/pages/%s/' % page.id)
resp = resp.click(href='/search_searchcell-%s/delete' % cell.id)
resp = resp.form.submit()
assert SearchCell.objects.count() == 0
def test_delete_cell(app, admin_user):
Page.objects.all().delete()
page = Page(title='One', slug='one', template_name='standard')
page.save()
cell = TextCell(page=page, placeholder='content', text='Foobar', order=0)
cell.save()
app = login(app)
resp = app.get('/manage/pages/%s/' % page.id)
resp = resp.click(href='/data_textcell-%s/delete' % cell.id)
resp = resp.form.submit()
assert TextCell.objects.count() == 0
def test_edit_cell_visibility(app, admin_user):
Page.objects.all().delete()
page = Page(title='One', slug='one', template_name='standard')
page.save()
cell = TextCell(page=page, placeholder='content', text='Foobar', order=0)
cell.save()
app = login(app)
resp = app.get('/manage/pages/%s/' % page.id)
resp = resp.click(href='/data_textcell-%s/visibility' % cell.id)
assert resp.form['cdata_textcell-%s-restricted_to_unlogged' % cell.id].checked is False
assert resp.form['cdata_textcell-%s-public' % cell.id].checked is False
resp.form['cdata_textcell-%s-public' % cell.id].checked = True
resp = resp.form.submit('submit')
assert TextCell.objects.get(id=cell.id).public is False
resp = app.get('/manage/pages/%s/' % page.id)
resp = resp.click(href='/data_textcell-%s/visibility' % cell.id)
assert resp.form['cdata_textcell-%s-restricted_to_unlogged' % cell.id].checked is False
assert resp.form['cdata_textcell-%s-public' % cell.id].checked is True
resp.form['cdata_textcell-%s-public' % cell.id].checked = False
resp.form['cdata_textcell-%s-restricted_to_unlogged' % cell.id].checked = True
resp = resp.form.submit('submit')
assert TextCell.objects.get(id=cell.id).restricted_to_unlogged is True
assert TextCell.objects.get(id=cell.id).public is True
def test_edit_cell_options(app, admin_user):
Page.objects.all().delete()
page = Page(title='One', slug='one', template_name='standard')
page.save()
cell = TextCell(page=page, placeholder='content', text='Foobar', order=0)
cell.save()
app = login(app)
resp = app.get('/manage/pages/%s/' % page.id)
resp = resp.click(href='/data_textcell-%s/options' % cell.id)
assert resp.form['cdata_textcell-%s-slug' % cell.id].value == ''
assert resp.form['cdata_textcell-%s-extra_css_class' % cell.id].value == ''
resp.form['cdata_textcell-%s-slug' % cell.id] = 'SLUG'
resp = resp.form.submit('submit')
assert TextCell.objects.get(id=cell.id).slug == 'SLUG'
assert 'SLUG' in app.get('/manage/pages/%s/' % page.id)
resp = app.get('/manage/pages/%s/' % page.id)
resp = resp.click(href='/data_textcell-%s/options' % cell.id)
resp.form['cdata_textcell-%s-slug' % cell.id] = ''
resp = resp.form.submit('submit')
assert TextCell.objects.get(id=cell.id).slug == ''
assert not 'SLUG' in app.get('/manage/pages/%s/' % page.id)
resp = app.get('/manage/pages/%s/' % page.id)
resp = resp.click(href='/data_textcell-%s/options' % cell.id)
resp.form['cdata_textcell-%s-extra_css_class' % cell.id] = 'CSS'
resp = resp.form.submit('submit')
assert TextCell.objects.get(id=cell.id).extra_css_class == 'CSS'
assert '[CSS]' in app.get('/manage/pages/%s/' % page.id)
def test_edit_cell_order(app, admin_user):
Page.objects.all().delete()
page = Page(title='One', slug='one', template_name='standard')
page.save()
cells = []
for i in range(5):
cells.append(TextCell(page=page, placeholder='content', text='Foobar%s' % i, order=i))
cells[-1].save()
params = []
new_order = [2, 3, 1, 4, 5]
for i, (cell, new_pos) in enumerate(zip(cells, new_order)):
params.append(('ph_data_textcell-%s' % cell.id, 'content')) # no placeholder change
params.append(('pos_data_textcell-%s' % cell.id, str(new_order[i])))
app = login(app)
resp = app.get('/manage/pages/%s/order?%s' % (page.id, urllib.urlencode(params)))
assert resp.status_code == 204
for i, cell in enumerate(cells):
assert TextCell.objects.get(id=cell.id).order == new_order[i]
def test_edit_text_cell(app, admin_user):
Page.objects.all().delete()
page = Page(title='One', slug='one', template_name='standard')
page.save()
app = login(app)
resp = app.get('/manage/pages/%s/' % page.id)
data_add_url = [x for x in resp.html.find_all('option') if x.text == 'Text'][0].get('data-add-url')
resp = app.get(data_add_url)
assert resp.location.endswith('/manage/pages/%s/' % page.id)
cells = CellBase.get_cells(page_id=page.id)
assert len(cells) == 1
assert isinstance(cells[0], TextCell)
resp = app.get('/manage/pages/%s/' % page.id)
resp.form['cdata_textcell-%s-text' % cells[0].id].value = 'Hello : World'
resp = resp.form.submit()
assert TextCell.objects.get(id=cells[0].id).text == 'Hello : World'
with override_settings(LANGUAGE_CODE='fr-fr'):
resp = app.get('/manage/pages/%s/' % page.id)
resp.form['cdata_textcell-%s-text' % cells[0].id].value = 'Hello : World'
resp = resp.form.submit()
assert TextCell.objects.get(id=cells[0].id).text == u'Hello\u00a0: World'
def test_edit_config_json_cell(app, admin_user):
Page.objects.all().delete()
page = Page(title='One', slug='one', template_name='standard')
page.save()
app = login(app)
resp = app.get('/manage/pages/%s/' % page.id)
options = [x.text for x in resp.html.find_all('option')]
assert not 'Foobar' in options
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-config-json-cell': {'name': 'Foobar', 'url': 'http://test/'}},
TEMPLATES=templates_settings):
resp = app.get('/manage/pages/%s/' % page.id)
options = [x.text for x in resp.html.find_all('option')]
assert 'Foobar' in options
data_add_url = [x for x in resp.html.find_all('option') if x.text == 'Foobar'][0].get('data-add-url')
resp = app.get(data_add_url)
assert resp.location.endswith('/manage/pages/%s/' % page.id)
cells = CellBase.get_cells(page_id=page.id)
assert len(cells) == 1
assert isinstance(cells[0], ConfigJsonCell)
assert cells[0].key == 'test-config-json-cell'
resp = app.get('/manage/pages/%s/' % page.id)
assert ('data-cell-reference="%s"' % cells[0].get_reference()) in resp.body
assert 'There are no options for this cell.' in resp.form.text
# make it configurable
with override_settings(JSON_CELL_TYPES=
{'test-config-json-cell': {
'name': 'Foobar',
'url': 'http://test/',
'form': [
{
'label': 'Test',
'type': 'string',
'varname': 'test',
},
{
'label': 'Test bool',
'type': 'bool',
'varname': 'test2',
'required': False,
},
{
'label': 'Test no type is string',
'varname': 'test3',
},
{
'label': 'Test text',
'type': 'text',
'varname': 'test4',
'required': False,
},
]}},
TEMPLATES=templates_settings):
resp = app.get('/manage/pages/%s/' % page.id)
assert not 'There are no options for this cell.' in resp.form.text
resp.form['c%s-test' % cells[0].get_reference()].value = 'Hello world'
resp.form['c%s-test3' % cells[0].get_reference()].value = 'Hello again'
resp = resp.form.submit()
assert resp.status_int == 302
assert resp.location.endswith('/manage/pages/%s/' % page.id)
resp = app.get('/manage/pages/%s/' % page.id)
assert resp.form['c%s-test' % cells[0].get_reference()].value == 'Hello world'
assert resp.form['c%s-test2' % cells[0].get_reference()].checked is False
assert resp.form['c%s-test3' % cells[0].get_reference()].value == 'Hello again'
resp = app.get('/manage/pages/%s/' % page.id)
assert ('data-cell-reference="%s"' % cells[0].get_reference()) in resp.body
resp.forms[0]['c%s-test' % cells[0].get_reference()].value = 'World Hello'
resp.forms[0]['c%s-test2' % cells[0].get_reference()].checked = True
assert resp.form['c%s-test4' % cells[0].get_reference()].tag == 'textarea'
resp.forms[0]['c%s-test4' % cells[0].get_reference()].value = 'Text Area'
resp = resp.form.submit(xhr=True)
assert resp.status_int == 200
assert resp.body.startswith('<p><label')
resp = app.get('/manage/pages/%s/' % page.id)
assert resp.form['c%s-test' % cells[0].get_reference()].value == 'World Hello'
assert resp.form['c%s-test2' % cells[0].get_reference()].checked is True
assert resp.form['c%s-test3' % cells[0].get_reference()].value == 'Hello again'
assert resp.form['c%s-test4' % cells[0].get_reference()].value == 'Text Area'
def test_logout(app, admin_user):
app = login(app)
app.get('/logout/')
assert app.get('/manage/', status=302).location.endswith('/login/?next=/manage/')
def test_asset_management(app, admin_user):
app = login(app)
resp = app.get('/manage/assets/')
assert 'have any asset yet.' in resp.body
# test upload
resp = app.get('/manage/assets/')
resp = resp.click('Upload')
resp.form['upload'] = Upload('test.png',
base64.decodestring('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQAAAAA3bvkkAAAACklEQVQI12NoAAAAggCB3UNq9AAAAABJRU5ErkJggg=='),
'image/png')
resp = resp.form.submit().follow()
# check file is now there
resp = app.get('/manage/assets/')
assert 'have any asset yet.' not in resp.body
# check there is also a thumbnail
thumbnail_filename = re.findall('src="/media/(.*thumb.*)"', resp.body)[0]
thumbnail_path = default_storage.path(thumbnail_filename)
assert os.path.exists(thumbnail_path)
thumbnail_contents = open(thumbnail_path).read()
# check overwriting
resp = resp.click('Overwrite')
resp.form['upload'] = Upload('test.png',
base64.decodestring('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVAAAACklEQVQI12NgAgAABAADRWoApgAA\nAABJRU5ErkJggg=='),
'image/png')
resp = resp.form.submit().follow()
resp.click('test.png')
assert re.findall('src="/media/(.*thumb.*)"', resp.body)[0] == thumbnail_filename
assert os.path.exists(thumbnail_path)
thumbnail_contents_new = open(thumbnail_path).read()
assert thumbnail_contents_new != thumbnail_contents
# test deletion
resp = resp.click('Delete')
assert 'Are you sure you want to delete' in resp.body
resp = resp.form.submit().follow()
assert 'have any asset yet.' in resp.body
def test_asset_management_search(app, admin_user):
app = login(app)
filepath = os.path.join(settings.CKEDITOR_UPLOAD_PATH, 'test.png')
pix = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQAAAAA3bvkkAAAACklEQVQI12NoAAAAggCB3UNq9AAAAABJRU5ErkJggg=='
default_storage.save(filepath, StringIO.StringIO(base64.decodestring(pix)))
assert os.path.exists(default_storage.path(filepath))
filepath = os.path.join(settings.CKEDITOR_UPLOAD_PATH, 'test.txt')
default_storage.save(filepath, StringIO.StringIO('hello world'))
filepath = os.path.join(settings.CKEDITOR_UPLOAD_PATH, 'foo.txt')
default_storage.save(filepath, StringIO.StringIO('foo bar baz'))
resp = app.get('/manage/assets/')
assert resp.body.count('<tr class="asset') == 3
resp.form['q'] = 'test'
resp = resp.form.submit()
assert resp.body.count('<tr class="asset') == 2
def test_asset_slots_management(app, admin_user):
app = login(app)
for path in ('uploads', 'assets'):
if os.path.exists(default_storage.path(path)):
shutil.rmtree(default_storage.path(path))
assert Asset.objects.count() == 0
with override_settings(COMBO_ASSET_SLOTS={'collectivity:banner': {'label': 'Banner'}}):
resp = app.get('/manage/assets/')
assert '>Banner<' in resp.body
assert '>Delete<' not in resp.body
resp = resp.click('Overwrite')
resp.form['upload'] = Upload('test.png',
base64.decodestring('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVAAAACklEQVQI12NgAgAABAADRWoApgAA\nAABJRU5ErkJggg=='),
'image/png')
resp = resp.form.submit().follow()
assert 'test.png' in resp.body
assert '>Delete<' in resp.body
assert Asset.objects.filter(key='collectivity:banner').count() == 1
assert app.get('/assets/collectivity:banner', status=302)['location'].endswith('test.png')
# upload a new version of image
resp = resp.click('Overwrite')
resp.form['upload'] = Upload('test2.png',
base64.decodestring('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVAAAACklEQVQI12NgAgAABAADRWoApgAA\nAABJRU5ErkJggg=='),
'image/png')
resp = resp.form.submit().follow()
assert 'test2.png' in resp.body
assert '>Delete<' in resp.body
assert Asset.objects.filter(key='collectivity:banner').count() == 1
resp = resp.click('Delete')
resp = resp.form.submit().follow()
assert '>Banner<' in resp.body
assert '>Delete<' not in resp.body
assert Asset.objects.filter(key='collectivity:banner').count() == 0
resp = app.get('/assets/collectivity:banner', status=404)
def test_menu_json(app, admin_user):
app.get('/manage/menu.json', status=302)
app = login(app)
resp = app.get('/manage/menu.json')
assert resp.headers['content-type'] == 'application/json'
assert resp.json[0]['label'] == 'Content Management'
resp = app.get('/manage/menu.json?callback=fooBar')
assert resp.headers['content-type'] == 'application/javascript'
assert resp.content.startswith('fooBar([{"')
def test_page_multiple_link_cells(app, admin_user):
Page.objects.all().delete()
page = Page(title='One', slug='one', template_name='standard')
page.save()
for i in range(10):
Page(title='page %d' % i, slug='page%d' % i, template_name='standard').save()
cell = LinkCell(page=page, placeholder='content', order=0)
cell.save()
patched_orig = Page.get_as_reordered_flat_hierarchy
app = login(app)
with mock.patch('combo.data.models.Page.get_as_reordered_flat_hierarchy') as func:
func.return_value = []
resp = app.get('/manage/pages/%s/' % page.id)
assert func.call_count == 1
def test_page_cell_placeholder(app, admin_user):
page = Page(title='One', slug='one', template_name='standard')
page.save()
cell = JsonCell(page=page, placeholder='content', order=0, url='http://example.com')
cell.save()
app = login(app)
resp = app.get('/manage/pages/%s/' % page.id)
assert re.findall('data-placeholder-key="(.*)">', resp.body) == ['content', 'footer']
# check a placeholder within a cell is included
cell.template_string = '{% load combo %}{% placeholder "foobar" name="Foobar" %}'
cell.save()
resp = app.get('/manage/pages/%s/' % page.id)
assert re.findall('data-placeholder-key="(.*)">', resp.body) == ['content', 'foobar', 'footer']
assert re.findall('<h2>(.*)</h2>', resp.body) == [
'Page - One', 'Content', 'JSON Feed / Foobar', 'Footer']
def test_page_familycell_placeholder(app, admin_user):
page = Page(title='My family', slug='my-family', template_name='standard')
page.save()
cell = FamilyInfosCell(page=page, placeholder='content', order=0)
cell.save()
app = login(app)
resp = app.get('/manage/pages/%s/' % page.id)
assert re.findall('data-placeholder-key="(.*)">', resp.body) == ['content', "family_unlinked_user", "footer"]
assert re.findall('<h2>(.*)</h2>', resp.body) == [
'Page - My family', 'Content',
'Family Information Cell / Top content for unlinked users', 'Footer']
def test_page_discover_placeholder_with_error_cells(app, admin_user):
page = Page(title='One', slug='one', template_name='standard')
page.save()
cell = JsonCell(page=page, placeholder='content', order=0, url='xx')
cell.template_string = '{% xxx %}'
cell.save()
app = login(app)
with mock.patch('combo.utils.requests.get') as requests_get:
data = {'data': [{'url': 'xxx', 'text': 'xxx'}]}
with pytest.raises(TemplateSyntaxError):
cell.render({})
resp = app.get('/manage/pages/%s/' % page.id)
assert re.findall('data-placeholder-key="(.*)">', resp.body) == ['content', 'footer']
def test_page_versionning(app, admin_user):
Page.objects.all().delete()
PageSnapshot.objects.all()
page = Page(title='One', slug='one')
page.save()
cell1 = TextCell(page=page, placeholder='content', text='Foobar1', order=0)
cell1.save()
cell2 = TextCell(page=page, placeholder='content', text='Foobar2', order=1)
cell2.save()
cell3 = TextCell(page=page, placeholder='content', text='Foobar3', order=1)
cell3.save()
anonymous_app = app
app = login(app)
resp = app.get('/manage/pages/%s/' % page.id, status=200)
# update title
resp = resp.click(href='.*/title')
resp.form['title'].value = 'One Two'
resp = resp.form.submit()
resp = resp.follow()
assert Page.objects.all()[0].title == 'One Two'
assert PageSnapshot.objects.all().count() == 1
# change cell text
resp.forms[0]['c%s-text' % cell1.get_reference()].value = 'Hello world'
resp = resp.forms[0].submit().follow()
assert PageSnapshot.objects.all().count() == 2
# reorder cells
params = []
for i, cell in enumerate([cell3, cell1, cell2]):
params.append(('ph_data_textcell-%s' % cell.id, 'content')) # no placeholder change
params.append(('pos_data_textcell-%s' % cell.id, str(i)))
app.get('/manage/pages/%s/order?%s' % (page.id, urllib.urlencode(params)))
assert PageSnapshot.objects.all().count() == 3
resp = resp.click('history')
assert resp.body.index('reordered cells') < resp.body.index('changed cell') < resp.body.index('changed title')
resp2 = resp.click('view', index=1)
assert resp2.body.index('Hello world') < resp2.body.index('Foobar3')
resp2 = resp.click('view', index=0)
assert resp2.body.index('Hello world') > resp2.body.index('Foobar3')
resp2 = resp.click('view', index=2)
assert 'Foobar1' in resp2.body
assert not 'Hello world' in resp2.body
assert Page.objects.all().count() == 1
# check with asynchronous cells
resp = app.get('/manage/pages/%s/add-cell-to-content/data_jsoncell/default/' % page.id)
resp = resp.follow()
resp.forms[3]['cdata_jsoncell-1-template_string'].value = 'A{{json.data.0.text}}B'
resp.forms[3]['cdata_jsoncell-1-url'].value = 'http://example.com'
resp = resp.forms[3].submit().follow()
assert PageSnapshot.objects.all().count() == 5 # add + change
resp.forms[3]['cdata_jsoncell-1-template_string'].value = 'C{{json.data.0.text}}D'
resp = resp.forms[3].submit().follow()
assert PageSnapshot.objects.all().count() == 6
resp.forms[1]['c%s-text' % cell1.get_reference()].value = 'Foo back to 1'
resp = resp.forms[0].submit().follow()
resp = resp.click('history')
assert 'added cell' in resp.body
resp2 = resp.click('view', index=1)
json_cell_url = re.findall(r'/ajax/cell/.*/data_jsoncell-.*/', resp2.body)[0]
with mock.patch('combo.utils.requests.get') as requests_get:
data = {'data': [{'url': 'xxx', 'text': 'xxx'}]}
requests_get.return_value = mock.Mock(content=json.dumps(data), status_code=200)
resp3 = app.get(json_cell_url)
assert resp3.body.strip() == 'CxxxD'
# previous version should return AxxxB
resp2 = resp.click('view', index=2)
json_cell_url = re.findall(r'/ajax/cell/.*/data_jsoncell-.*/', resp2.body)[0]
with mock.patch('combo.utils.requests.get') as requests_get:
data = {'data': [{'url': 'xxx', 'text': 'xxx'}]}
requests_get.return_value = mock.Mock(content=json.dumps(data), status_code=200)
resp3 = app.get(json_cell_url)
assert resp3.body.strip() == 'AxxxB'
# check anonymous users can't get to cells from snapshots
app.get('/logout/')
resp3 = app.get(json_cell_url, status=403)
# restore a snapshot
app = login(app)
resp = resp.click('restore', index=6)
resp = resp.form.submit()
resp = resp.follow()
resp2 = resp.click('see online')
assert resp2.body.index('Foobar1') < resp2.body.index('Foobar2') < resp2.body.index('Foobar3')
# clean it up
Page.snapshots.all().delete()
assert Page.objects.count() == 1
assert TextCell.objects.count() == 3
assert JsonCell.objects.count() == 0