combo/tests/test_search.py

280 lines
10 KiB
Python

import json
import os
import pytest
import mock
from django.conf import settings
from django.test import Client, override_settings
from django.test.client import RequestFactory
from django.core.management import call_command
from django.core.urlresolvers import reverse
from haystack.exceptions import SkipDocument
from combo.apps.search.models import SearchCell
from combo.data.models import Page, JsonCell, TextCell, MenuCell, LinkCell
from combo.data.search_indexes import PageIndex
pytestmark = pytest.mark.django_db
client = Client()
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',
}
}
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):
delattr(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_service = 'search1'
cell.save()
resp = cell.render({})
assert 'input' in resp
assert 'id="combo-search-input-%s"' % cell.pk in resp
cell.slug = 'var-name'
context = {'request': RequestFactory().get('/?q_var_name=searchme')}
resp = cell.render(context)
assert "combo_search_input_%s.val('searchme');" % cell.pk 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 = client.get('/ajax/search/%s/?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.content
resp = client.get('/ajax/search/%s/?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.content
response['data'] = [{'url': 'http://test', 'text': 'barbarbar'}]
resp = client.get('/ajax/search/%s/?q=foo' % cell.pk, status=200)
assert resp.content.count('<li>') == 1
assert '<li><a href="http://test">barbarbar</a>' in resp.content
response['data'] = [{'url': 'http://test', 'text': 'barbarbar',
'description': 'this is <b>html</b>'}]
resp = client.get('/ajax/search/%s/?q=foo' % cell.pk, status=200)
assert resp.content.count('<li>') == 1
assert '<li><a href="http://test">barbarbar</a>' in resp.content
assert 'this is <b>html</b>' in resp.content
with override_settings(TEMPLATE_VARS=TEMPLATE_VARS):
cell._search_service = '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 = client.get('/ajax/search/%s/?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 = client.get('/ajax/search/%s/?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.content
assert 'search_url=http://search.example.net/' in resp.content
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_service = '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(content=json.dumps(data), status_code=200)
resp = app.get(url)
assert requests_get.call_args[0][0] == 'http://www.example.net/search/foo/'
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_service = '_text'
assert cell.is_visible()
def test_search_contents():
page = Page(title='example page', slug='example-page')
page.save()
# no indexation of private cells (is_visible check)
cell = TextCell(page=page, text='foobar', public=False, order=0)
assert cell.render_for_search() == ''
# 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.save()
page_index = PageIndex()
assert page_index.get_model() is Page
assert page_index.prepare_url(page) == '/example-page/'
page_index.prepare(page)
page.public = False
with pytest.raises(SkipDocument):
page_index.prepare(page)
page.public = True
cell = TextCell(page=page, text='<p>foobar</p>', order=0)
cell.save()
prepared_data = page_index.prepare(page)
assert 'foobar' in prepared_data['text']
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='on').save()
page_index = PageIndex()
prepared_data = page_index.prepare(page)
assert 'barfoo' in prepared_data['text']
assert not 'foobar' in prepared_data['text']
def test_search_api(app):
page = Page(title='example page', slug='example-page')
page.save()
cell = TextCell(page=page, 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, text='<p>other baz</p>', order=0)
cell.save()
page_index = PageIndex()
page_index.reindex()
resp = app.get('/api/search/?q=foobar', status=404)
cell = SearchCell(page=page, _search_service='_text', order=0)
cell.save()
resp = app.get('/api/search/?q=foobar', status=200)
assert len(resp.json['data']) == 1
assert resp.json['data'][0]['text'] == 'example page'
resp = app.get('/api/search/?q=other', status=200)
assert len(resp.json['data']) == 1
assert resp.json['data'][0]['text'] == 'second page'
resp = app.get('/api/search/?q=baz', status=200)
assert len(resp.json['data']) == 2
resp = app.get('/api/search/?q=quux', status=200)
assert len(resp.json['data']) == 0
def test_update_index_command(app):
call_command('clear_index', interactive=False)
call_command('update_index') # empty site
page = Page(title='example page', slug='example-page')
page.save()
cell = SearchCell(page=page, _search_service='_text', order=0)
cell.save()
call_command('update_index')
resp = app.get('/api/search/?q=foobar', status=200)
assert len(resp.json['data']) == 0
LinkCell(title='foobar', url='http://example.net', page=page, order=0).save()
call_command('update_index')
resp = app.get('/api/search/?q=foobar', status=200)
assert len(resp.json['data']) == 1
assert resp.json['data'][0]['text'] == 'foobar'
assert resp.json['data'][0]['description'] is None
assert resp.json['data'][0]['url'] == 'http://example.net'
LinkCell(title='baz', url='http://example.net', page=page, order=0).save()
call_command('update_index')
resp = app.get('/api/search/?q=baz', status=200)
assert len(resp.json['data']) == 1
assert resp.json['data'][0]['url'] == 'http://example.net'
# add a second link with the same target
LinkCell(title='bar', url='http://example.net', page=page, order=0).save()
call_command('update_index')
resp = app.get('/api/search/?q=baz', status=200)
assert len(resp.json['data']) == 1
assert resp.json['data'][0]['url'] == 'http://example.net'
resp = app.get('/api/search/?q=bar', status=200)
assert len(resp.json['data']) == 1
assert resp.json['data'][0]['url'] == 'http://example.net'