import base64
import json
import os
import re
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, Group
from django.template import TemplateSyntaxError
from django.test import override_settings
from django.utils.http import urlencode
from django.utils.six import BytesIO
from django.utils.six.moves.urllib import parse as urlparse
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')
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.text
assert "This site doesn't have any page yet." in resp.text
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.text
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_edit_page_unknown_template(app, admin_user):
Page.objects.all().delete()
page = Page(title='One', slug='one', template_name='broken')
page.save()
app = login(app)
resp = app.get('/manage/pages/%s/' % page.id)
assert 'Unknown (broken)' in resp.text
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.text
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'), mode='rb').read(), 'image/jpeg')
resp = resp.form.submit()
assert resp.location.endswith('/manage/pages/%s/' % page.id)
resp = resp.follow()
assert '
Page - One
' in resp.text
assert 'Page - One' in resp.text
assert not 'Delete' in resp.text
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 '' in resp.text
assert 'Delete only this page' in resp.text
assert 'Delete this page and all subpages' in resp.text
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 '' in resp.text
assert 'Delete only this page' in resp.text
assert 'Delete this page and all subpages' in resp.text
resp.form['choice'].value = 'delete-all'
resp = resp.forms[0].submit()
assert resp.location.endswith('/manage/')
assert Page.objects.count() == 0
def test_page_reorder(app, admin_user):
Page.objects.all().delete()
page1 = Page(title='One', slug='one', parent=None, order=0, template_name='standard')
page1.save()
page2 = Page(title='Two', slug='two', parent=None, order=1, template_name='standard')
page2.save()
page3 = Page(title='Three', slug='three', parent=page2, order=2, template_name='standard')
page3.save()
page4 = Page(title='Four', slug='four', parent=page2, order=3, template_name='standard')
page4.save()
ordered_ids = [x.id for x in Page.get_as_reordered_flat_hierarchy(Page.objects.all())]
ordered_ids = [page1.id, page2.id, page3.id, page4.id]
# move page4 before page3
app = login(app)
resp = app.get('/manage/pages/order', params={
'moved-page-id': page4.id,
'moved-page-new-parent': page2.id,
'new-order': ','.join([str(x) for x in [page1.id, page2.id, page4.id, page3.id]])})
ordered_ids = [x.id for x in Page.get_as_reordered_flat_hierarchy(Page.objects.all())]
ordered_ids = [page1.id, page2.id, page4.id, page3.id]
# move page4 to level0
resp = app.get('/manage/pages/order', params={
'moved-page-id': page4.id,
'moved-page-new-parent': '',
'new-order': ','.join([str(x) for x in [page1.id, page4.id, page2.id, page3.id]])})
ordered_ids = [x.id for x in Page.get_as_reordered_flat_hierarchy(Page.objects.all())]
ordered_ids = [page1.id, page4.id, page2.id, page3.id]
# change slug to check for autochange on duplicate
page4.slug = 'three'
page4.save()
# move it as a sibling of page3
resp = app.get('/manage/pages/order', params={
'moved-page-id': page4.id,
'moved-page-new-parent': page2.id,
'new-order': ','.join([str(x) for x in [page1.id, page2.id, page4.id, page3.id]])})
assert Page.objects.get(id=page4.id).slug.startswith('three-')
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', b'invalid content', 'application/json')
resp = resp.form.submit()
assert 'File is not in the expected JSON format.' in resp.text
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.text
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.text
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.text.strip().startswith('