Skip to content

Commit

Permalink
Merge 823c744 into a01a0fa
Browse files Browse the repository at this point in the history
  • Loading branch information
rafalp committed Oct 12, 2019
2 parents a01a0fa + 823c744 commit d6a2384
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 19 deletions.
8 changes: 8 additions & 0 deletions misago/core/tests/test_context_processors_hook.py
@@ -0,0 +1,8 @@
from ..context_processors import hooks


def test_context_processors_hook_can_inject_context(mocker):
plugin = mocker.Mock(return_value={"plugin": True})
mocker.patch("misago.core.context_processors.context_processors_hooks", [plugin])
context = hooks(None)
assert context == {"plugin": True}
4 changes: 4 additions & 0 deletions misago/hooks.py
@@ -1,3 +1,7 @@
apipatterns = []
urlpatterns = []
context_processors = []

new_registrations_validators = []
post_search_filters = []
post_validators = []
5 changes: 5 additions & 0 deletions misago/threads/filtersearch.py
@@ -1,5 +1,6 @@
from django.utils.module_loading import import_string

from .. import hooks
from ..conf import settings

filters_list = settings.MISAGO_POST_SEARCH_FILTERS
Expand All @@ -8,6 +9,10 @@

def filter_search(search, filters=None):
filters = filters or SEARCH_FILTERS

for search_filter in filters:
search = search_filter(search) or search
for search_filter in hooks.post_search_filters:
search = search_filter(search) or search

return search
63 changes: 44 additions & 19 deletions misago/threads/tests/test_search.py
Expand Up @@ -5,6 +5,17 @@
from ...users.test import AuthenticatedUserTestCase


def index_post(post):
if post.id == post.thread.first_post_id:
post.set_search_document(post.thread.title)
else:
post.set_search_document()
post.save(update_fields=["search_document"])

post.update_search_vector()
post.save(update_fields=["search_vector"])


class SearchApiTests(AuthenticatedUserTestCase):
def setUp(self):
super().setUp()
Expand All @@ -13,16 +24,6 @@ def setUp(self):

self.api_link = reverse("misago:api:search")

def index_post(self, post):
if post.id == post.thread.first_post_id:
post.set_search_document(post.thread.title)
else:
post.set_search_document()
post.save(update_fields=["search_document"])

post.update_search_vector()
post.save(update_fields=["search_vector"])

def test_no_query(self):
"""api handles no search query"""
response = self.client.get(self.api_link)
Expand Down Expand Up @@ -51,7 +52,7 @@ def test_short_query(self):
"""api handles short search query"""
thread = test.post_thread(self.category)
post = test.reply_thread(thread, message="Lorem ipsum dolor.")
self.index_post(post)
index_post(post)

response = self.client.get("%s?q=ip" % self.api_link)
self.assertEqual(response.status_code, 200)
Expand All @@ -67,7 +68,7 @@ def test_wrong_query(self):
"""api handles query miss"""
thread = test.post_thread(self.category)
post = test.reply_thread(thread, message="Lorem ipsum dolor.")
self.index_post(post)
index_post(post)

response = self.client.get("%s?q=elit" % self.api_link)
self.assertEqual(response.status_code, 200)
Expand All @@ -83,7 +84,7 @@ def test_hidden_post(self):
"""hidden posts are extempt from search"""
thread = test.post_thread(self.category)
post = test.reply_thread(thread, message="Lorem ipsum dolor.", is_hidden=True)
self.index_post(post)
index_post(post)

response = self.client.get("%s?q=ipsum" % self.api_link)
self.assertEqual(response.status_code, 200)
Expand All @@ -101,7 +102,7 @@ def test_unapproved_post(self):
post = test.reply_thread(
thread, message="Lorem ipsum dolor.", is_unapproved=True
)
self.index_post(post)
index_post(post)

response = self.client.get("%s?q=ipsum" % self.api_link)
self.assertEqual(response.status_code, 200)
Expand All @@ -117,7 +118,7 @@ def test_query(self):
"""api handles search query"""
thread = test.post_thread(self.category)
post = test.reply_thread(thread, message="Lorem ipsum dolor.")
self.index_post(post)
index_post(post)

response = self.client.get("%s?q=ipsum" % self.api_link)
self.assertEqual(response.status_code, 200)
Expand All @@ -134,10 +135,10 @@ def test_query(self):
def test_thread_title_search(self):
"""api searches threads by title"""
thread = test.post_thread(self.category, title="Atmosphere of mars")
self.index_post(thread.first_post)
index_post(thread.first_post)

post = test.reply_thread(thread, message="Lorem ipsum dolor.")
self.index_post(post)
index_post(post)

response = self.client.get("%s?q=mars atmosphere" % self.api_link)
self.assertEqual(response.status_code, 200)
Expand All @@ -155,7 +156,7 @@ def test_complex_query(self):
"""api handles complex query that uses fulltext search facilities"""
thread = test.post_thread(self.category)
post = test.reply_thread(thread, message="Atmosphere of Mars")
self.index_post(post)
index_post(post)

response = self.client.get("%s?q=Mars atmosphere" % self.api_link)
self.assertEqual(response.status_code, 200)
Expand All @@ -176,7 +177,7 @@ def test_filtered_query(self):
thread, message="You just do MMM in 4th minute and its pwnt"
)

self.index_post(post)
index_post(post)

response = self.client.get("%s?q=MMM" % self.api_link)
self.assertEqual(response.status_code, 200)
Expand Down Expand Up @@ -207,3 +208,27 @@ def setUp(self):
self.api_link = reverse(
"misago:api:search", kwargs={"search_provider": "threads"}
)


def test_post_search_filters_hook_is_used_by_threads_search(
db, user_client, mocker, thread
):
def search_filter(search):
return search.replace("apple phone", "iphone")

mocker.patch(
"misago.threads.filtersearch.hooks.post_search_filters", [search_filter]
)

post = test.reply_thread(thread, message="Lorem ipsum iphone dolor met.")
index_post(post)

response = user_client.get("/api/search/?q=apple phone")

reponse_json = response.json()
assert "threads" in [p["id"] for p in reponse_json]
for provider in reponse_json:
if provider["id"] == "threads":
results = provider["results"]["results"]
assert len(results) == 1
assert results[0]["id"] == post.id
15 changes: 15 additions & 0 deletions misago/threads/tests/test_validate_post.py
@@ -1,3 +1,4 @@
from django.core.exceptions import ValidationError
from django.urls import reverse

from ...categories.models import Category
Expand Down Expand Up @@ -86,3 +87,17 @@ def test_empty_input(self):
"post": ["This field may not be blank."],
},
)


def test_post_validators_hook_is_used_by_posting_api(db, user_client, mocker, thread):
def validator(context, data):
raise ValidationError("ERROR FROM PLUGIN")

mocker.patch("misago.threads.validators.hooks.post_validators", [validator])

response = user_client.post(
f"/api/threads/{thread.id}/posts/", {"post": "Lorem ipsum dolor met"}
)

assert response.status_code == 400
assert response.json() == {"non_field_errors": ["ERROR FROM PLUGIN"]}
3 changes: 3 additions & 0 deletions misago/threads/validators.py
Expand Up @@ -3,6 +3,7 @@
from django.utils.translation import gettext as _
from django.utils.translation import ngettext

from .. import hooks
from ..categories import THREADS_ROOT_NAME
from ..categories.models import Category
from ..categories.permissions import can_browse_category, can_see_category
Expand Down Expand Up @@ -108,5 +109,7 @@ def validate_post(context, data, validators=None):

for validator in validators:
data = validator(context, data) or data
for validator in hooks.post_validators:
data = validator(context, data) or data

return data
20 changes: 20 additions & 0 deletions misago/users/tests/test_user_create_api.py
Expand Up @@ -553,3 +553,23 @@ def test_registration_creates_user_with_whitespace_password(self):
self.assertTrue(test_user.check_password(password))

self.assertIn("Welcome", mail.outbox[0].subject)


@override_dynamic_settings(account_activation="none")
def test_new_registrations_validators_hook_is_used_by_registration_api(
db, client, mocker
):
def validator(request, cleaned_data, add_error):
add_error("username", "ERROR FROM PLUGIN")

mocker.patch(
"misago.users.validators.hooks.new_registrations_validators", [validator]
)

response = client.post(
"/api/users/",
{"username": "User", "email": "user@example.com", "password": "PASSW0RD123"},
)

assert response.status_code == 400
assert response.json() == {"username": ["ERROR FROM PLUGIN"]}
4 changes: 4 additions & 0 deletions misago/users/validators.py
Expand Up @@ -12,6 +12,7 @@
from django.utils.translation import ngettext
from requests.exceptions import RequestException

from .. import hooks
from ..conf import settings
from .bans import get_email_ban, get_username_ban

Expand Down Expand Up @@ -157,6 +158,9 @@ def raise_validation_error(*_):

def validate_new_registration(request, cleaned_data, add_error=None, validators=None):
validators = validators or REGISTRATION_VALIDATORS

add_error = add_error or raise_validation_error
for validator in validators:
validator(request, cleaned_data, add_error)
for validator in hooks.new_registrations_validators:
validator(request, cleaned_data, add_error)

0 comments on commit d6a2384

Please sign in to comment.