import json import os import pytest import re import mock from django.conf import settings from django.test import 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.engines import engines from combo.apps.search.models import SearchCell from combo.data.models import Page, JsonCell, TextCell, MenuCell, LinkCell from combo.data.search_indexes import PageIndex 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.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 = 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 '
foobar
', 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='foobar
', 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='foobar
', order=0, placeholder='_off').save() TextCell(page=page, text='barfoo
', 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='foobar baz
', order=0) cell.save() second_page = Page(title='second page', slug='second-page') second_page.save() cell = TextCell(page=second_page, text='other baz
', order=0) cell.save() page_index = PageIndex() page_index.reindex() resp = app.get('/api/search/?q=foobar', status=404) cell = SearchCell(page=page, _search_services={'data': ['_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_services={'data': ['_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' def test_manager_search_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) resp = app.get(resp.html.find('option', **{'data-add-url': re.compile('search_searchcell')})['data-add-url']) cells = Page.objects.get(id=page.id).get_cells() assert len(cells) == 1 assert isinstance(cells[0], SearchCell) with override_settings(KNOWN_SERVICES={}): resp = app.get('/manage/pages/%s/' % page.id) assert ('data-cell-reference="%s"' % cells[0].get_reference()) in resp.text assert len(resp.form['c%s-_search_services' % cells[0].get_reference()].options) == 1 with SearchServices(SEARCH_SERVICES): resp = app.get('/manage/pages/%s/' % page.id) assert len(resp.form['c%s-_search_services' % cells[0].get_reference()].options) == 4 # simulate reordering of options resp.form['c%s-_search_services' % cells[0].get_reference()].options = [ (u'search_tmpl', False, u'Search with template'), (u'search_alternate_key', False, u'Search with alternate key'), (u'_text', False, u'Page Contents'), (u'search1', False, u'Search 1')] resp.form['c%s-_search_services' % cells[0].get_reference()].value = ['search_tmpl', '_text'] resp = resp.form.submit() assert resp.status_int == 302 # check selected engines are selected and the first items of the list resp = app.get('/manage/pages/%s/' % page.id) assert set(resp.form['c%s-_search_services' % cells[0].get_reference()].value) == set(['search_tmpl', '_text']) assert resp.form['c%s-_search_services' % cells[0].get_reference()].options[0][0] == 'search_tmpl' assert resp.form['c%s-_search_services' % cells[0].get_reference()].options[1][0] == '_text' # check there's no crash if search engines are removed from config resp = app.get('/manage/pages/%s/' % page.id) assert resp.form['c%s-_search_services' % cells[0].get_reference()].value == ['_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 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