combo/tests/test_search.py

671 lines
28 KiB
Python

import json
import os
import pytest
import mock
from django.conf import settings
from django.contrib.auth.models import AnonymousUser, User, Group
from django.db import connection
from django.test import override_settings
from django.test.client import RequestFactory
from django.test.utils import CaptureQueriesContext
from django.urls import reverse
from django.utils.http import urlencode
from combo.apps.search.engines import engines
from combo.apps.search.models import SearchCell, IndexedCell
from combo.apps.search.utils import index_site, search_site
from combo.data.models import Page, JsonCell, TextCell, MenuCell, LinkCell, PageSnapshot
from .test_manager import login
pytestmark = pytest.mark.django_db
SEARCH_SERVICES = {
'search1': {
'label': 'Search 1',
'url': 'http://www.example.net/search/?q=%(q)s',
},
'search_tmpl': {
'label': 'Search with template',
'url': '[search_url]?q=%(q)s',
},
'search_alternate_key': {
'label': 'Search with alternate key',
'url': 'http://www.example.net/search/?q=%(q)s',
'data_key': 'results',
},
}
TEMPLATE_VARS = {'search_url': 'http://search.example.net/'}
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):
with SearchServices(SEARCH_SERVICES):
page = Page(title='Search', slug='search_page', template_name='standard')
page.save()
cell = SearchCell(page=page, placeholder='content', order=0)
cell._search_services = {'data': ['search1']}
cell.input_placeholder = 'my placeholder'
cell.save()
resp = cell.render({})
assert 'input' in resp
assert 'id="combo-search-input-%s"' % cell.pk in resp
assert 'autofocus' not in resp
assert 'placeholder="my placeholder"' in resp
cell.autofocus = True
cell.save()
resp = cell.render({})
assert 'autofocus' in resp
cell.slug = 'var-name'
context = {'request': RequestFactory().get('/?q_var_name=searchme')}
resp = cell.render(context)
assert "$input.val('searchme');" in resp
with mock.patch('combo.apps.search.models.requests.get') as requests_get:
response = {'err': 0, 'data': []}
mock_json = mock.Mock()
mock_json.json.return_value = response
requests_get.return_value = mock_json
resp = app.get('/ajax/search/%s/search1/?q=foo' % cell.pk, status=200)
assert requests_get.call_args[0][0] == 'http://www.example.net/search/?q=foo'
assert '<li>' not in resp.text
assert 'no result found' in resp.text
resp = app.get('/ajax/search/%s/search1/?q=foo%%23bar' % cell.pk, status=200)
assert requests_get.call_args[0][0] == 'http://www.example.net/search/?q=foo%23bar'
assert '<li>' not in resp.text
assert 'no result found' in resp.text
response['data'] = [{'url': 'http://test', 'text': 'barbarbar'}]
resp = app.get('/ajax/search/%s/search1/?q=foo' % cell.pk, status=200)
assert resp.text.count('<li>') == 1
assert '<li><a href="http://test">barbarbar</a>' in resp.text
assert 'no result found' not in resp.text
response['data'] = [{'url': 'http://test', 'text': 'barbarbar',
'description': 'this is <b>html</b>'}]
resp = app.get('/ajax/search/%s/search1/?q=foo' % cell.pk, status=200)
assert resp.text.count('<li>') == 1
assert '<li><a href="http://test">barbarbar</a>' in resp.text
assert 'this is <b>html</b>' in resp.text
assert 'no result found' not in resp.text
resp = app.get('/ajax/search/%s/search1/?q=' % cell.pk, status=200)
assert '<li>' not in resp.text
assert 'no result found' not in resp.text
cell._search_services = {'data': ['search_alternate_key']}
cell.save()
response = {'results': [{'url': 'http://test', 'text': 'barbarbar'}]}
mock_json.json.return_value = response
resp = app.get('/ajax/search/%s/search_alternate_key/?q=foo' % cell.pk, status=200)
assert resp.text.count('<li>') == 1
assert '<li><a href="http://test">barbarbar</a>' in resp.text
# search engine does not return valid JSON
class FakedResponse(mock.Mock):
def json(self):
return json.loads(self.content)
requests_get.return_value = FakedResponse(content='notjson', status_code=200)
resp = app.get('/ajax/search/%s/search_alternate_key/?q=bar' % cell.pk, status=200)
assert requests_get.call_args[0][0] == 'http://www.example.net/search/?q=bar'
assert '<li>' not in resp.text
assert 'no result found' in resp.text
requests_get.return_value = FakedResponse(content='500withbadjson', status_code=500)
resp = app.get('/ajax/search/%s/search_alternate_key/?q=foo' % cell.pk, status=200)
assert requests_get.call_args[0][0] == 'http://www.example.net/search/?q=foo'
assert '<li>' not in resp.text
assert 'no result found' in resp.text
with override_settings(TEMPLATE_VARS=TEMPLATE_VARS):
cell._search_services = {'data': ['search_tmpl']}
cell.save()
with mock.patch('combo.apps.search.models.requests.get') as requests_get:
response = {'err': 0, 'data': []}
mock_json = mock.Mock()
mock_json.json.return_value = response
requests_get.return_value = mock_json
resp = app.get('/ajax/search/%s/search_tmpl/?q=foo' % cell.pk, status=200)
assert requests_get.call_args[0][0] == 'http://search.example.net/?q=foo'
# TEMPLATE_VARS are accessible in template
cell.slug = 'searchfoo'
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(TEMPLATES=templates_settings):
resp = app.get('/ajax/search/%s/search_tmpl/?q=bar' % cell.pk, status=200)
assert requests_get.call_args[0][0] == 'http://search.example.net/?q=bar'
assert 'searchfoo results.data=[]' in resp.text
assert 'search_url=http://search.example.net/' in resp.text
def test_search_global_context(app):
with SearchServices(SEARCH_SERVICES):
page = Page(title='Search', slug='search_page', template_name='standard')
page.save()
cell = SearchCell(page=page, placeholder='content', order=0)
cell._search_services = {'data': ['search1']}
cell.save()
assert cell.varname == ''
cell.slug = 'search-item'
cell.save()
assert cell.varname == 'search_item'
jsoncell = JsonCell(page=page, placeholder='content', order=0)
jsoncell.url = 'http://www.example.net/search/[search_item]/'
jsoncell.save()
url = reverse('combo-public-ajax-page-cell',
kwargs={'page_pk': page.id, 'cell_reference': jsoncell.get_reference()}) + \
'?search_item=foo'
with mock.patch('combo.utils.requests.get') as requests_get:
data = {'data': []}
requests_get.return_value = mock.Mock(json=lambda: data, status_code=200)
resp = app.get(url)
assert requests_get.call_args[0][0] == 'http://www.example.net/search/foo/'
def test_search_custom_templates(app):
services = {
'search2': {
'label': 'Search 2',
'url': 'http://www.example.net/search/?q=%(q)s',
'hit_url_template': 'http://example.net/{{id}}/',
'hit_label_template': '{{a}} {{b}}',
'hit_description_template': 'description {{a}}',
}
}
with SearchServices(services):
page = Page(title='Search', slug='search_page', template_name='standard')
page.save()
cell = SearchCell(page=page, placeholder='content', order=0)
cell._search_services = {'data': ['search2']}
cell.save()
with mock.patch('combo.apps.search.models.requests.get') as requests_get:
response = {
'err': 0,
'data': [{'id': '123', 'a': 'A', 'b': 'B'}],
}
mock_json = mock.Mock()
mock_json.json.return_value = response
requests_get.return_value = mock_json
resp = app.get('/ajax/search/%s/search2/?q=foo' % cell.pk, status=200)
assert resp.text.count('<li>') == 1
assert '<li><a href="http://example.net/123/">A B</a>' in resp.text
assert '<div>description A</div>' in resp.text
def test_search_cell_visibility(app):
page = Page(title='example page', slug='example-page')
page.save()
with SearchServices(SEARCH_SERVICES):
cell = SearchCell(page=page, order=0)
assert not cell.is_visible()
cell._search_services = {'data': ['_text']}
del cell.search_services # clear cache
assert cell.is_visible()
def test_search_contents():
page = Page(title='example page', slug='example-page')
page.save()
# private cells are indexed
cell = TextCell(page=page, text='foobar', public=False, order=0)
assert cell.render_for_search().strip() == 'foobar'
# no indexation of empty cells (is_relevant check)
cell = TextCell(page=page, text='', order=0)
assert cell.render_for_search() == ''
# indexation
cell = TextCell(page=page, text='<p>foobar</p>', order=0)
assert cell.render_for_search().strip() == 'foobar'
# no indexation of menu cells
cell = MenuCell(page=page, order=0)
assert cell.render_for_search() == ''
def test_search_contents_index():
page = Page(title='example page', slug='example-page')
page.public = True
page.save()
cell = TextCell(page=page, placeholder='content', text='<p>foobar</p>', order=0)
cell.save()
request = RequestFactory().get('/')
request.user = AnonymousUser()
hits = search_site(request, 'foobar')
assert len(hits) == 0
index_site()
hits = search_site(request, 'foobar')
assert len(hits) == 1
def test_search_contents_technical_placeholder():
page = Page(title='example page', slug='example-page')
page.save()
TextCell(page=page, text='<p>foobar</p>', order=0, placeholder='_off').save()
TextCell(page=page, text='<p>barfoo</p>', order=0, placeholder='content').save()
request = RequestFactory().get('/')
request.user = AnonymousUser()
index_site()
hits = search_site(request, 'foobar')
assert len(hits) == 0
hits = search_site(request, 'barfoo')
assert len(hits) == 1
def test_search_api(app):
page = Page(title='example page', slug='example-page')
page.save()
cell = TextCell(page=page, placeholder='content', text='<p>foobar baz</p>', order=0)
cell.save()
second_page = Page(title='second page', slug='second-page')
second_page.save()
cell = TextCell(page=second_page, placeholder='content', text='<p>other baz</p>', order=0)
cell.save()
index_site()
cell = SearchCell(page=page, placeholder='content', _search_services={'data': ['_text']}, order=0)
cell.save()
resp = app.get('/ajax/search/%s/_text/?q=foobar' % cell.id, status=200)
assert resp.text.count('<li') == 1
assert 'example page' in resp.text
resp = app.get('/ajax/search/%s/_text/?q=other' % cell.id, status=200)
assert resp.text.count('<li') == 1
assert 'second page' in resp.text
resp = app.get('/ajax/search/%s/_text/?q=baz' % cell.id, status=200)
assert resp.text.count('<li') == 2
resp = app.get('/ajax/search/%s/_text/?q=quux' % cell.id, status=200)
assert resp.text.count('<li') == 0
def test_search_on_root_page_api(app):
# not indexed: with sub_slug
page = Page.objects.create(title='example page', slug='example-page', sub_slug='foo')
TextCell.objects.create(page=page, placeholder='content', text='<p>foobar baz</p>', order=0)
second_page = Page.objects.create(title='second page', slug='second-page')
TextCell.objects.create(page=second_page, placeholder='content', text='<p>other baz</p>', order=0)
sub_second_page = Page.objects.create(parent=second_page, title='sub second page', slug='sub-second-page')
TextCell.objects.create(page=sub_second_page, placeholder='content', text='<p>other baz</p>', order=0)
# not indexed: with snapshot
third_page = Page.objects.create(title='second page', slug='third-page')
TextCell.objects.create(page=third_page, placeholder='content', text='<p>other baz again</p>', order=0)
third_page.snapshot = PageSnapshot.objects.create(page=third_page)
third_page.save()
index_site()
cell = SearchCell.objects.create(page=page, placeholder='content', _search_services={'data': ['_text']}, order=1)
resp = app.get('/ajax/search/%s/_text/?q=baz' % cell.pk, status=200)
assert resp.text.count('<li') == 2
cell._search_services = {'data': ['_text_page_second-page']}
cell.save()
resp = app.get('/ajax/search/%s/_text_page_second-page/?q=baz' % cell.pk, status=200)
assert resp.text.count('<li') == 2
cell._search_services = {'data': ['_text_page_sub-second-page']}
cell.save()
resp = app.get('/ajax/search/%s/_text_page_sub-second-page/?q=baz' % cell.pk, status=200)
assert resp.text.count('<li') == 1
# invalid page, search everywhere
# with sub_slug
cell._search_services = {'data': ['_text_page_example-page']}
cell.save()
resp = app.get('/ajax/search/%s/_text_page_example-page/?q=baz' % cell.pk, status=200)
assert resp.text.count('<li') == 2
# with snapshot
cell._search_services = {'data': ['_text_page_third-page']}
cell.save()
resp = app.get('/ajax/search/%s/_text_page_third-page/?q=baz' % cell.pk, status=200)
assert resp.text.count('<li') == 2
# page does not exists, search everywhere
cell._search_services = {'data': ['_text_page_foo']}
cell.save()
resp = app.get('/ajax/search/%s/_text_page_foo/?q=baz' % cell.pk, status=200)
assert resp.text.count('<li') == 2
# slug is not unique, search everywhere
page.slug = 'sub-second-page'
page.sub_slug = ''
page.save()
cell._search_services = {'data': ['_text_page_sub-second-page']}
cell.save()
resp = app.get('/ajax/search/%s/_text_page_sub-second-page/?q=baz' % cell.pk, status=200)
assert resp.text.count('<li') == 2
def test_search_external_links(app):
page = Page(title='example page', slug='example-page')
page.save()
cell = SearchCell(page=page, placeholder='content', _search_services={'data': ['_text']}, order=0)
cell.save()
index_site()
request = RequestFactory().get('/')
request.user = AnonymousUser()
hits = search_site(request, 'foobar')
assert len(hits) == 0
LinkCell(title='foobar', url='http://example.net', page=page, placeholder='content', order=0).save()
index_site()
hits = search_site(request, 'foobar')
assert len(hits) == 1
assert hits[0]['text'] == 'foobar'
assert hits[0]['url'] == 'http://example.net'
# second link with same target
LinkCell(title='baz', url='http://example.net', page=page, placeholder='content', order=0).save()
index_site()
# add a second link with the same target
hits = search_site(request, 'baz')
assert len(hits) == 1
assert hits[0]['text'] in ('foobar', 'baz')
assert hits[0]['url'] == 'http://example.net'
hits = search_site(request, 'foobar')
assert len(hits) == 1
assert hits[0]['text'] in ('foobar', 'baz')
assert hits[0]['url'] == 'http://example.net'
def test_manager_search_cell(settings, app, admin_user):
page = Page.objects.create(title='One', slug='one', template_name='standard')
cell = SearchCell.objects.create(page=page, placeholder='content', order=0)
app = login(app)
settings.KNOWN_SERVICES = {}
assert cell._search_services == {}
resp = app.get('/manage/pages/%s/' % page.pk)
assert '/manage/search/pages/%s/cell/search_searchcell-%s/engine/_text/add/' % (page.pk, cell.pk) in resp.text
assert '/manage/search/pages/%s/cell/search_searchcell-%s/engine/_text/delete/' % (page.pk, cell.pk) not in resp.text
settings.COMBO_SEARCH_SERVICES = SEARCH_SERVICES
resp = app.get('/manage/pages/%s/' % page.pk)
assert '/manage/search/pages/%s/cell/search_searchcell-%s/engine/_text/add/' % (page.pk, cell.pk) in resp.text
assert '/manage/search/pages/%s/cell/search_searchcell-%s/engine/search1/add/' % (page.pk, cell.pk) in resp.text
assert '/manage/search/pages/%s/cell/search_searchcell-%s/engine/search_tmpl/add/' % (page.pk, cell.pk) in resp.text
assert '/manage/search/pages/%s/cell/search_searchcell-%s/engine/search_alternate_key/add/' % (page.pk, cell.pk) in resp.text
assert '/manage/search/pages/%s/cell/search_searchcell-%s/engine/_text/delete/' % (page.pk, cell.pk) not in resp.text
assert '/manage/search/pages/%s/cell/search_searchcell-%s/engine/search1/delete/' % (page.pk, cell.pk) not in resp.text
assert '/manage/search/pages/%s/cell/search_searchcell-%s/engine/search_tmpl/delete/' % (page.pk, cell.pk) not in resp.text
assert '/manage/search/pages/%s/cell/search_searchcell-%s/engine/search_alternate_key/delete/' % (page.pk, cell.pk) not in resp.text
# add engines
resp = resp.click(href='.*/search_searchcell-%s/engine/_text/add/' % cell.pk)
resp = resp.form.submit('submit')
assert resp.status_int == 302
assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.pk, cell.get_reference()))
resp = app.get('/manage/pages/%s/' % page.pk)
resp = resp.click(href='.*/search_searchcell-%s/engine/search1/add/' % cell.pk)
resp = app.get('/manage/pages/%s/' % page.pk)
resp = resp.click(href='.*/search_searchcell-%s/engine/search_tmpl/add/' % cell.pk)
cell.refresh_from_db()
assert cell._search_services == {'data': ['_text', 'search1', 'search_tmpl']}
resp = app.get('/manage/pages/%s/' % page.pk)
# '_text' is always available
assert '/manage/search/pages/%s/cell/search_searchcell-%s/engine/_text/add/' % (page.pk, cell.pk) in resp.text
assert '/manage/search/pages/%s/cell/search_searchcell-%s/engine/search1/add/' % (page.pk, cell.pk) not in resp.text
assert '/manage/search/pages/%s/cell/search_searchcell-%s/engine/search_tmpl/add/' % (page.pk, cell.pk) not in resp.text
assert '/manage/search/pages/%s/cell/search_searchcell-%s/engine/search_alternate_key/add/' % (page.pk, cell.pk) in resp.text
assert '/manage/search/pages/%s/cell/search_searchcell-%s/engine/_text/delete/' % (page.pk, cell.pk) in resp.text
assert '/manage/search/pages/%s/cell/search_searchcell-%s/engine/search1/delete/' % (page.pk, cell.pk) in resp.text
assert '/manage/search/pages/%s/cell/search_searchcell-%s/engine/search_tmpl/delete/' % (page.pk, cell.pk) in resp.text
assert '/manage/search/pages/%s/cell/search_searchcell-%s/engine/search_alternate_key/delete/' % (page.pk, cell.pk) not in resp.text
# delete engines
resp = resp.click(href='.*/search_searchcell-%s/engine/_text/delete/' % cell.pk)
assert resp.status_int == 302
assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.pk, cell.get_reference()))
cell.refresh_from_db()
assert cell._search_services == {'data': ['search1', 'search_tmpl']}
settings.COMBO_SEARCH_SERVICES = {}
# check there's no crash if search engines are removed from config
resp = app.get('/manage/pages/%s/' % page.pk)
assert '/manage/search/pages/%s/cell/search_searchcell-%s/engine/search1/add/' % (page.pk, cell.pk) not in resp.text
assert '/manage/search/pages/%s/cell/search_searchcell-%s/engine/search_tmpl/add/' % (page.pk, cell.pk) not in resp.text
assert '/manage/search/pages/%s/cell/search_searchcell-%s/engine/search_alternate_key/add/' % (page.pk, cell.pk) not in resp.text
assert '/manage/search/pages/%s/cell/search_searchcell-%s/engine/search1/delete/' % (page.pk, cell.pk) not in resp.text
assert '/manage/search/pages/%s/cell/search_searchcell-%s/engine/search_tmpl/delete/' % (page.pk, cell.pk) not in resp.text
assert '/manage/search/pages/%s/cell/search_searchcell-%s/engine/search_alternate_key/delete/' % (page.pk, cell.pk) not in resp.text
# add engines on page and sub pages
resp = resp.click(href='.*/search_searchcell-%s/engine/_text/add/' % cell.pk)
assert list(resp.context['form']['selected_page'].field.queryset) == [page]
resp = resp.form.submit('submit')
assert resp.status_int == 302
assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.pk, cell.get_reference()))
cell.refresh_from_db()
assert cell._search_services == {'data': ['search1', 'search_tmpl', '_text']}
resp = app.get('/manage/pages/%s/' % page.pk)
assert '/manage/search/pages/%s/cell/search_searchcell-%s/engine/_text/add/' % (page.pk, cell.pk) in resp.text
assert '/manage/search/pages/%s/cell/search_searchcell-%s/engine/_text/delete/' % (page.pk, cell.pk) in resp.text
assert '/manage/search/pages/%s/cell/search_searchcell-%s/engine/_text_page_one/delete/' % (page.pk, cell.pk) not in resp.text
resp = resp.click(href='.*/search_searchcell-%s/engine/_text/add/' % cell.pk)
resp.form['selected_page'] = page.pk
resp = resp.form.submit('submit')
assert resp.status_int == 302
assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.pk, cell.get_reference()))
cell.refresh_from_db()
assert cell._search_services == {'data': ['search1', 'search_tmpl', '_text', '_text_page_one']}
resp = app.get('/manage/pages/%s/' % page.pk)
assert '/manage/search/pages/%s/cell/search_searchcell-%s/engine/_text/add/' % (page.pk, cell.pk) in resp.text
assert '/manage/search/pages/%s/cell/search_searchcell-%s/engine/_text/delete/' % (page.pk, cell.pk) in resp.text
assert '/manage/search/pages/%s/cell/search_searchcell-%s/engine/_text_page_one/delete/' % (page.pk, cell.pk) in resp.text
def test_manager_search_cell_order(settings, app, admin_user):
settings.COMBO_SEARCH_SERVICES = SEARCH_SERVICES
page = Page.objects.create(title='One', slug='one', template_name='standard')
cell = SearchCell.objects.create(
page=page, placeholder='content', order=0,
_search_services={'data': ['_text', 'search1', 'search_tmpl']})
params = []
new_order = [2, 3, 1]
for i, (service_slug, new_pos) in enumerate(zip(cell._search_services['data'], new_order)):
params.append(('pos_%s' % service_slug, str(new_pos)))
app = login(app)
resp = app.get('/manage/search/pages/%s/cell/%s/engine/order?%s' % (page.pk, cell.get_reference(), urlencode(params)))
assert resp.status_code == 204
cell.refresh_from_db()
assert cell._search_services == {'data': ['search_tmpl', '_text', 'search1']}
def test_manager_waiting_index_message(app, admin_user):
page = Page.objects.create(title='One', slug='one', template_name='standard')
cell = SearchCell.objects.create(page=page, placeholder='content', order=0)
app = login(app)
resp = app.get('/manage/pages/%s/' % page.pk)
assert 'Content indexing has been scheduled' not in resp.text
resp = resp.click(href='.*/search_searchcell-%s/engine/_text/add/' % cell.pk)
resp = resp.form.submit('submit')
resp = app.get('/manage/pages/%s/' % page.pk)
assert 'Content indexing has been scheduled' in resp.text
index_site()
resp = app.get('/manage/pages/%s/' % page.pk)
assert 'Content indexing has been scheduled' not in resp.text
def test_wcs_search_engines(app):
with override_settings(KNOWN_SERVICES={}):
search_engines = engines.get_engines()
assert 'tracking-code' not in search_engines.keys()
assert len([x for x in search_engines.keys() if x.startswith('formdata:')]) == 0
for key, engine in engines.get_engines().items():
if key.startswith('formdata:'):
assert '&include-anonymised=off' in engine['url']
def test_profile_search_engines(app):
search_engines = engines.get_engines()
assert 'users' not in search_engines.keys()
with override_settings(KNOWN_SERVICES={'authentic': {'default': {'title': 'authentic', 'url': 'https://authentic/'}}}):
search_engines = engines.get_engines()
assert 'users' not in search_engines.keys()
page = Page(slug='users', title='Users', sub_slug='(?P<name_id>[a-z0-9]+)')
page.save()
search_engines = engines.get_engines()
assert 'users' in search_engines.keys()
def test_private_search(app):
page = Page(title='example page', slug='example-page')
page.save()
TextCell(page=page, placeholder='content', text='<p>foobar</p>', order=0, public=False).save()
TextCell(page=page, placeholder='content', text='<p>barfoo</p>', order=0, public=True).save()
request = RequestFactory().get('/')
request.user = AnonymousUser()
index_site()
hits = search_site(request, 'foobar')
assert len(hits) == 0
hits = search_site(request, 'barfoo')
assert len(hits) == 1
request.user = User.objects.create_user(username='normal-user')
hits = search_site(request, 'foobar')
assert len(hits) == 1
hits = search_site(request, 'barfoo')
assert len(hits) == 1
def test_restricted_search(app):
group = Group(name='plop')
group.save()
page = Page(title='example page', slug='example-page')
page.save()
cell = TextCell(page=page, placeholder='content', text='<p>foobar</p>', order=0, public=False)
cell.save()
cell.groups.set([group])
TextCell(page=page, placeholder='content', text='<p>barfoo</p>', order=0, public=False).save()
index_site()
# first cell is restricted, it's not found
request = RequestFactory().get('/')
request.user = User.objects.create_user(username='normal-user')
hits = search_site(request, 'foobar')
assert len(hits) == 0
hits = search_site(request, 'barfoo')
assert len(hits) == 1
page.groups.set([group])
index_site()
# page is restricted, no cell is found
hits = search_site(request, 'foobar')
assert len(hits) == 0
hits = search_site(request, 'barfoo')
assert len(hits) == 0
# user is in group, gets a result
request.user.groups.set([group])
hits = search_site(request, 'foobar')
assert len(hits) == 1
hits = search_site(request, 'barfoo')
assert len(hits) == 1
# cell is excluded from group view
cell.restricted_to_unlogged = True
cell.save()
index_site()
hits = search_site(request, 'foobar')
assert len(hits) == 0
hits = search_site(request, 'barfoo')
assert len(hits) == 1
def test_no_sub_slug_search(app):
page = Page(title='example page', slug='example-page')
page.save()
TextCell(page=page, placeholder='content', text='<p>foobar</p>', order=0, public=True).save()
page = Page(title='example page with sub_slug', slug='sub-slugged-page',
sub_slug='(?P<foo>\d+)')
page.save()
TextCell(page=page, placeholder='content', text='<p>barfoo</p>', order=0, public=True).save()
request = RequestFactory().get('/')
request.user = AnonymousUser()
index_site()
hits = search_site(request, 'foobar')
assert len(hits) == 1
hits = search_site(request, 'barfoo')
assert len(hits) == 0
def test_index_site_inactive_placeholder(app):
page = Page.objects.create(title='page', slug='example-page')
cell = TextCell.objects.create(page=page, placeholder='content', text='<p>foobar</p>', order=0)
assert cell.is_placeholder_active() is True
index_site()
assert IndexedCell.objects.count() == 1
cell.placeholder = ''
cell.save()
assert cell.is_placeholder_active() is False
index_site()
assert IndexedCell.objects.count() == 0
def test_index_site_num_queries(app):
group = Group.objects.create(name='plop')
for i in range(0, 10):
page = Page.objects.create(title='page %s' % i, slug='example-page-%s' % i)
page.groups.set([group])
for j in range(0, 5):
cell = TextCell.objects.create(page=page, placeholder='content', text='<p>foobar %s</p>' % j, order=j, public=False)
cell.groups.set([group])
index_site() # populate cache
assert IndexedCell.objects.count() == 50
with CaptureQueriesContext(connection) as ctx:
index_site()
assert len(ctx.captured_queries) == 225