mirror of
https://github.com/zulip/zulip.git
synced 2025-11-12 18:06:44 +00:00
mypy: Annotate zerver/tests/test_narrow.py
This commit is contained in:
committed by
showell
parent
eb35d53ed1
commit
4eb6adf547
@@ -41,7 +41,6 @@ tools/deprecated/inject-messages/inject-messages
|
|||||||
zproject/settings.py
|
zproject/settings.py
|
||||||
zproject/test_settings.py
|
zproject/test_settings.py
|
||||||
zerver/tests/test_decorators.py
|
zerver/tests/test_decorators.py
|
||||||
zerver/tests/test_narrow.py
|
|
||||||
""".split()
|
""".split()
|
||||||
|
|
||||||
# We don't run mypy on contrib_bots, since the code there will
|
# We don't run mypy on contrib_bots, since the code there will
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
from django.db import connection
|
from django.db import connection
|
||||||
from django.test import override_settings
|
from django.test import override_settings
|
||||||
from sqlalchemy.sql import (
|
from sqlalchemy.sql import (
|
||||||
and_, select, column, compiler
|
and_, select, column,
|
||||||
)
|
)
|
||||||
|
from sqlalchemy.sql import compiler # type: ignore
|
||||||
|
|
||||||
from zerver.models import (
|
from zerver.models import (
|
||||||
Realm, Recipient, Stream, Subscription, UserProfile, Attachment,
|
Realm, Recipient, Stream, Subscription, UserProfile, Attachment,
|
||||||
@@ -18,6 +20,7 @@ from zerver.lib.message import (
|
|||||||
from zerver.lib.narrow import (
|
from zerver.lib.narrow import (
|
||||||
build_narrow_filter,
|
build_narrow_filter,
|
||||||
)
|
)
|
||||||
|
from zerver.lib.str_utils import force_bytes
|
||||||
from zerver.lib.sqlalchemy_utils import get_sqlalchemy_connection
|
from zerver.lib.sqlalchemy_utils import get_sqlalchemy_connection
|
||||||
from zerver.lib.test_helpers import (
|
from zerver.lib.test_helpers import (
|
||||||
POSTRequestMock,
|
POSTRequestMock,
|
||||||
@@ -30,29 +33,33 @@ from zerver.lib.test_classes import (
|
|||||||
from zerver.views.messages import (
|
from zerver.views.messages import (
|
||||||
exclude_muting_conditions,
|
exclude_muting_conditions,
|
||||||
get_old_messages_backend, ok_to_include_history,
|
get_old_messages_backend, ok_to_include_history,
|
||||||
NarrowBuilder, BadNarrowOperator
|
NarrowBuilder, BadNarrowOperator, Query
|
||||||
)
|
)
|
||||||
|
|
||||||
from typing import Text
|
from typing import Mapping, Sequence, Tuple, Generic, Union, Any, Text
|
||||||
from six.moves import range
|
from six.moves import range
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import ujson
|
import ujson
|
||||||
|
|
||||||
def get_sqlalchemy_query_params(query):
|
def get_sqlalchemy_query_params(query):
|
||||||
dialect = get_sqlalchemy_connection().dialect
|
# type: (Text) -> Dict[Text, Text]
|
||||||
|
dialect = get_sqlalchemy_connection().dialect # type: ignore
|
||||||
comp = compiler.SQLCompiler(dialect, query)
|
comp = compiler.SQLCompiler(dialect, query)
|
||||||
comp.compile()
|
comp.compile()
|
||||||
return comp.params
|
return comp.params
|
||||||
|
|
||||||
def fix_ws(s):
|
def fix_ws(s):
|
||||||
|
# type: (Text) -> Text
|
||||||
return re.sub('\s+', ' ', str(s)).strip()
|
return re.sub('\s+', ' ', str(s)).strip()
|
||||||
|
|
||||||
def get_recipient_id_for_stream_name(realm, stream_name):
|
def get_recipient_id_for_stream_name(realm, stream_name):
|
||||||
|
# type: (Realm, Text) -> Text
|
||||||
stream = get_stream(stream_name, realm)
|
stream = get_stream(stream_name, realm)
|
||||||
return get_recipient(Recipient.STREAM, stream.id).id
|
return get_recipient(Recipient.STREAM, stream.id).id
|
||||||
|
|
||||||
def mute_stream(realm, user_profile, stream_name):
|
def mute_stream(realm, user_profile, stream_name):
|
||||||
|
# type: (Realm, Text, Text) -> None
|
||||||
stream = Stream.objects.get(realm=realm, name=stream_name)
|
stream = Stream.objects.get(realm=realm, name=stream_name)
|
||||||
recipient = Recipient.objects.get(type_id=stream.id, type=Recipient.STREAM)
|
recipient = Recipient.objects.get(type_id=stream.id, type=Recipient.STREAM)
|
||||||
subscription = Subscription.objects.get(recipient=recipient, user_profile=user_profile)
|
subscription = Subscription.objects.get(recipient=recipient, user_profile=user_profile)
|
||||||
@@ -61,183 +68,225 @@ def mute_stream(realm, user_profile, stream_name):
|
|||||||
|
|
||||||
class NarrowBuilderTest(ZulipTestCase):
|
class NarrowBuilderTest(ZulipTestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
# type: () -> None
|
||||||
self.realm = get_realm_by_string_id('zulip')
|
self.realm = get_realm_by_string_id('zulip')
|
||||||
self.user_profile = get_user_profile_by_email("hamlet@zulip.com")
|
self.user_profile = get_user_profile_by_email("hamlet@zulip.com")
|
||||||
self.builder = NarrowBuilder(self.user_profile, column('id'))
|
self.builder = NarrowBuilder(self.user_profile, column('id'))
|
||||||
self.raw_query = select([column("id")], None, "zerver_message")
|
self.raw_query = select([column("id")], None, "zerver_message")
|
||||||
|
|
||||||
def test_add_term_using_not_defined_operator(self):
|
def test_add_term_using_not_defined_operator(self):
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='not-defined', operand='any')
|
term = dict(operator='not-defined', operand='any')
|
||||||
self.assertRaises(BadNarrowOperator, self._build_query, term)
|
self.assertRaises(BadNarrowOperator, self._build_query, term)
|
||||||
|
|
||||||
def test_add_term_using_stream_operator(self):
|
def test_add_term_using_stream_operator(self):
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='stream', operand='Scotland')
|
term = dict(operator='stream', operand='Scotland')
|
||||||
self._do_add_term_test(term, 'WHERE recipient_id = :recipient_id_1')
|
self._do_add_term_test(term, 'WHERE recipient_id = :recipient_id_1')
|
||||||
|
|
||||||
def test_add_term_using_stream_operator_and_negated(self): # NEGATED
|
def test_add_term_using_stream_operator_and_negated(self): # NEGATED
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='stream', operand='Scotland', negated=True)
|
term = dict(operator='stream', operand='Scotland', negated=True)
|
||||||
self._do_add_term_test(term, 'WHERE recipient_id != :recipient_id_1')
|
self._do_add_term_test(term, 'WHERE recipient_id != :recipient_id_1')
|
||||||
|
|
||||||
def test_add_term_using_stream_operator_and_non_existing_operand_should_raise_error(self): # NEGATED
|
def test_add_term_using_stream_operator_and_non_existing_operand_should_raise_error(self): # NEGATED
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='stream', operand='NonExistingStream')
|
term = dict(operator='stream', operand='NonExistingStream')
|
||||||
self.assertRaises(BadNarrowOperator, self._build_query, term)
|
self.assertRaises(BadNarrowOperator, self._build_query, term)
|
||||||
|
|
||||||
def test_add_term_using_is_operator_and_private_operand(self):
|
def test_add_term_using_is_operator_and_private_operand(self):
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='is', operand='private')
|
term = dict(operator='is', operand='private')
|
||||||
self._do_add_term_test(term, 'WHERE type = :type_1 OR type = :type_2')
|
self._do_add_term_test(term, 'WHERE type = :type_1 OR type = :type_2')
|
||||||
|
|
||||||
def test_add_term_using_is_operator_private_operand_and_negated(self): # NEGATED
|
def test_add_term_using_is_operator_private_operand_and_negated(self): # NEGATED
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='is', operand='private', negated=True)
|
term = dict(operator='is', operand='private', negated=True)
|
||||||
self._do_add_term_test(term, 'WHERE NOT (type = :type_1 OR type = :type_2)')
|
self._do_add_term_test(term, 'WHERE NOT (type = :type_1 OR type = :type_2)')
|
||||||
|
|
||||||
def test_add_term_using_is_operator_and_non_private_operand(self):
|
def test_add_term_using_is_operator_and_non_private_operand(self):
|
||||||
|
# type: () -> None
|
||||||
for operand in ['starred', 'mentioned', 'alerted']:
|
for operand in ['starred', 'mentioned', 'alerted']:
|
||||||
term = dict(operator='is', operand=operand)
|
term = dict(operator='is', operand=operand)
|
||||||
self._do_add_term_test(term, 'WHERE (flags & :flags_1) != :param_1')
|
self._do_add_term_test(term, 'WHERE (flags & :flags_1) != :param_1')
|
||||||
|
|
||||||
def test_add_term_using_is_operator_non_private_operand_and_negated(self): # NEGATED
|
def test_add_term_using_is_operator_non_private_operand_and_negated(self): # NEGATED
|
||||||
|
# type: () -> None
|
||||||
for operand in ['starred', 'mentioned', 'alerted']:
|
for operand in ['starred', 'mentioned', 'alerted']:
|
||||||
term = dict(operator='is', operand=operand, negated=True)
|
term = dict(operator='is', operand=operand, negated=True)
|
||||||
self._do_add_term_test(term, 'WHERE (flags & :flags_1) = :param_1')
|
self._do_add_term_test(term, 'WHERE (flags & :flags_1) = :param_1')
|
||||||
|
|
||||||
def test_add_term_using_non_supported_operator_should_raise_error(self):
|
def test_add_term_using_non_supported_operator_should_raise_error(self):
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='is', operand='non_supported')
|
term = dict(operator='is', operand='non_supported')
|
||||||
self.assertRaises(BadNarrowOperator, self._build_query, term)
|
self.assertRaises(BadNarrowOperator, self._build_query, term)
|
||||||
|
|
||||||
def test_add_term_using_topic_operator_and_lunch_operand(self):
|
def test_add_term_using_topic_operator_and_lunch_operand(self):
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='topic', operand='lunch')
|
term = dict(operator='topic', operand='lunch')
|
||||||
self._do_add_term_test(term, 'WHERE upper(subject) = upper(:param_1)')
|
self._do_add_term_test(term, 'WHERE upper(subject) = upper(:param_1)')
|
||||||
|
|
||||||
def test_add_term_using_topic_operator_lunch_operand_and_negated(self): # NEGATED
|
def test_add_term_using_topic_operator_lunch_operand_and_negated(self): # NEGATED
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='topic', operand='lunch', negated=True)
|
term = dict(operator='topic', operand='lunch', negated=True)
|
||||||
self._do_add_term_test(term, 'WHERE upper(subject) != upper(:param_1)')
|
self._do_add_term_test(term, 'WHERE upper(subject) != upper(:param_1)')
|
||||||
|
|
||||||
def test_add_term_using_topic_operator_and_personal_operand(self):
|
def test_add_term_using_topic_operator_and_personal_operand(self):
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='topic', operand='personal')
|
term = dict(operator='topic', operand='personal')
|
||||||
self._do_add_term_test(term, 'WHERE upper(subject) = upper(:param_1)')
|
self._do_add_term_test(term, 'WHERE upper(subject) = upper(:param_1)')
|
||||||
|
|
||||||
def test_add_term_using_topic_operator_personal_operand_and_negated(self): # NEGATED
|
def test_add_term_using_topic_operator_personal_operand_and_negated(self): # NEGATED
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='topic', operand='personal', negated=True)
|
term = dict(operator='topic', operand='personal', negated=True)
|
||||||
self._do_add_term_test(term, 'WHERE upper(subject) != upper(:param_1)')
|
self._do_add_term_test(term, 'WHERE upper(subject) != upper(:param_1)')
|
||||||
|
|
||||||
def test_add_term_using_sender_operator(self):
|
def test_add_term_using_sender_operator(self):
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='sender', operand='othello@zulip.com')
|
term = dict(operator='sender', operand='othello@zulip.com')
|
||||||
self._do_add_term_test(term, 'WHERE sender_id = :param_1')
|
self._do_add_term_test(term, 'WHERE sender_id = :param_1')
|
||||||
|
|
||||||
def test_add_term_using_sender_operator_and_negated(self): # NEGATED
|
def test_add_term_using_sender_operator_and_negated(self): # NEGATED
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='sender', operand='othello@zulip.com', negated=True)
|
term = dict(operator='sender', operand='othello@zulip.com', negated=True)
|
||||||
self._do_add_term_test(term, 'WHERE sender_id != :param_1')
|
self._do_add_term_test(term, 'WHERE sender_id != :param_1')
|
||||||
|
|
||||||
def test_add_term_using_sender_operator_with_non_existing_user_as_operand(self): # NEGATED
|
def test_add_term_using_sender_operator_with_non_existing_user_as_operand(self): # NEGATED
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='sender', operand='non-existing@zulip.com')
|
term = dict(operator='sender', operand='non-existing@zulip.com')
|
||||||
self.assertRaises(BadNarrowOperator, self._build_query, term)
|
self.assertRaises(BadNarrowOperator, self._build_query, term)
|
||||||
|
|
||||||
def test_add_term_using_pm_with_operator_and_not_the_same_user_as_operand(self):
|
def test_add_term_using_pm_with_operator_and_not_the_same_user_as_operand(self):
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='pm-with', operand='othello@zulip.com')
|
term = dict(operator='pm-with', operand='othello@zulip.com')
|
||||||
self._do_add_term_test(term, 'WHERE sender_id = :sender_id_1 AND recipient_id = :recipient_id_1 OR sender_id = :sender_id_2 AND recipient_id = :recipient_id_2')
|
self._do_add_term_test(term, 'WHERE sender_id = :sender_id_1 AND recipient_id = :recipient_id_1 OR sender_id = :sender_id_2 AND recipient_id = :recipient_id_2')
|
||||||
|
|
||||||
def test_add_term_using_pm_with_operator_not_the_same_user_as_operand_and_negated(self): # NEGATED
|
def test_add_term_using_pm_with_operator_not_the_same_user_as_operand_and_negated(self): # NEGATED
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='pm-with', operand='othello@zulip.com', negated=True)
|
term = dict(operator='pm-with', operand='othello@zulip.com', negated=True)
|
||||||
self._do_add_term_test(term, 'WHERE NOT (sender_id = :sender_id_1 AND recipient_id = :recipient_id_1 OR sender_id = :sender_id_2 AND recipient_id = :recipient_id_2)')
|
self._do_add_term_test(term, 'WHERE NOT (sender_id = :sender_id_1 AND recipient_id = :recipient_id_1 OR sender_id = :sender_id_2 AND recipient_id = :recipient_id_2)')
|
||||||
|
|
||||||
def test_add_term_using_pm_with_operator_the_same_user_as_operand(self):
|
def test_add_term_using_pm_with_operator_the_same_user_as_operand(self):
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='pm-with', operand='hamlet@zulip.com')
|
term = dict(operator='pm-with', operand='hamlet@zulip.com')
|
||||||
self._do_add_term_test(term, 'WHERE sender_id = :sender_id_1 AND recipient_id = :recipient_id_1')
|
self._do_add_term_test(term, 'WHERE sender_id = :sender_id_1 AND recipient_id = :recipient_id_1')
|
||||||
|
|
||||||
def test_add_term_using_pm_with_operator_the_same_user_as_operand_and_negated(self): # NEGATED
|
def test_add_term_using_pm_with_operator_the_same_user_as_operand_and_negated(self): # NEGATED
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='pm-with', operand='hamlet@zulip.com', negated=True)
|
term = dict(operator='pm-with', operand='hamlet@zulip.com', negated=True)
|
||||||
self._do_add_term_test(term, 'WHERE NOT (sender_id = :sender_id_1 AND recipient_id = :recipient_id_1)')
|
self._do_add_term_test(term, 'WHERE NOT (sender_id = :sender_id_1 AND recipient_id = :recipient_id_1)')
|
||||||
|
|
||||||
def test_add_term_using_pm_with_operator_and_more_than_user_as_operand(self):
|
def test_add_term_using_pm_with_operator_and_more_than_user_as_operand(self):
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='pm-with', operand='hamlet@zulip.com, othello@zulip.com')
|
term = dict(operator='pm-with', operand='hamlet@zulip.com, othello@zulip.com')
|
||||||
self._do_add_term_test(term, 'WHERE recipient_id = :recipient_id_1')
|
self._do_add_term_test(term, 'WHERE recipient_id = :recipient_id_1')
|
||||||
|
|
||||||
def test_add_term_using_pm_with_operator_more_than_user_as_operand_and_negated(self): # NEGATED
|
def test_add_term_using_pm_with_operator_more_than_user_as_operand_and_negated(self): # NEGATED
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='pm-with', operand='hamlet@zulip.com, othello@zulip.com', negated=True)
|
term = dict(operator='pm-with', operand='hamlet@zulip.com, othello@zulip.com', negated=True)
|
||||||
self._do_add_term_test(term, 'WHERE recipient_id != :recipient_id_1')
|
self._do_add_term_test(term, 'WHERE recipient_id != :recipient_id_1')
|
||||||
|
|
||||||
def test_add_term_using_pm_with_operator_with_non_existing_user_as_operand(self):
|
def test_add_term_using_pm_with_operator_with_non_existing_user_as_operand(self):
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='pm-with', operand='non-existing@zulip.com')
|
term = dict(operator='pm-with', operand='non-existing@zulip.com')
|
||||||
self.assertRaises(BadNarrowOperator, self._build_query, term)
|
self.assertRaises(BadNarrowOperator, self._build_query, term)
|
||||||
|
|
||||||
def test_add_term_using_pm_with_operator_with_existing_and_non_existing_user_as_operand(self):
|
def test_add_term_using_pm_with_operator_with_existing_and_non_existing_user_as_operand(self):
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='pm-with', operand='othello@zulip.com,non-existing@zulip.com')
|
term = dict(operator='pm-with', operand='othello@zulip.com,non-existing@zulip.com')
|
||||||
self.assertRaises(BadNarrowOperator, self._build_query, term)
|
self.assertRaises(BadNarrowOperator, self._build_query, term)
|
||||||
|
|
||||||
def test_add_term_using_id_operator(self):
|
def test_add_term_using_id_operator(self):
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='id', operand=555)
|
term = dict(operator='id', operand=555)
|
||||||
self._do_add_term_test(term, 'WHERE id = :param_1')
|
self._do_add_term_test(term, 'WHERE id = :param_1')
|
||||||
|
|
||||||
def test_add_term_using_id_operator_and_negated(self): # NEGATED
|
def test_add_term_using_id_operator_and_negated(self): # NEGATED
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='id', operand=555, negated=True)
|
term = dict(operator='id', operand=555, negated=True)
|
||||||
self._do_add_term_test(term, 'WHERE id != :param_1')
|
self._do_add_term_test(term, 'WHERE id != :param_1')
|
||||||
|
|
||||||
@override_settings(USING_PGROONGA=False)
|
@override_settings(USING_PGROONGA=False)
|
||||||
def test_add_term_using_search_operator(self):
|
def test_add_term_using_search_operator(self):
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='search', operand='"french fries"')
|
term = dict(operator='search', operand='"french fries"')
|
||||||
self._do_add_term_test(term, 'WHERE (lower(content) LIKE lower(:content_1) OR lower(subject) LIKE lower(:subject_1)) AND (search_tsvector @@ plainto_tsquery(:param_2, :param_3))')
|
self._do_add_term_test(term, 'WHERE (lower(content) LIKE lower(:content_1) OR lower(subject) LIKE lower(:subject_1)) AND (search_tsvector @@ plainto_tsquery(:param_2, :param_3))')
|
||||||
|
|
||||||
@override_settings(USING_PGROONGA=False)
|
@override_settings(USING_PGROONGA=False)
|
||||||
def test_add_term_using_search_operator_and_negated(self): # NEGATED
|
def test_add_term_using_search_operator_and_negated(self): # NEGATED
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='search', operand='"french fries"', negated=True)
|
term = dict(operator='search', operand='"french fries"', negated=True)
|
||||||
self._do_add_term_test(term, 'WHERE NOT (lower(content) LIKE lower(:content_1) OR lower(subject) LIKE lower(:subject_1)) AND NOT (search_tsvector @@ plainto_tsquery(:param_2, :param_3))')
|
self._do_add_term_test(term, 'WHERE NOT (lower(content) LIKE lower(:content_1) OR lower(subject) LIKE lower(:subject_1)) AND NOT (search_tsvector @@ plainto_tsquery(:param_2, :param_3))')
|
||||||
|
|
||||||
@override_settings(USING_PGROONGA=True)
|
@override_settings(USING_PGROONGA=True)
|
||||||
def test_add_term_using_search_operator_pgroonga(self):
|
def test_add_term_using_search_operator_pgroonga(self):
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='search', operand='"french fries"')
|
term = dict(operator='search', operand='"french fries"')
|
||||||
self._do_add_term_test(term, 'WHERE search_pgroonga @@ :search_pgroonga_1')
|
self._do_add_term_test(term, 'WHERE search_pgroonga @@ :search_pgroonga_1')
|
||||||
|
|
||||||
@override_settings(USING_PGROONGA=True)
|
@override_settings(USING_PGROONGA=True)
|
||||||
def test_add_term_using_search_operator_and_negated_pgroonga(self): # NEGATED
|
def test_add_term_using_search_operator_and_negated_pgroonga(self): # NEGATED
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='search', operand='"french fries"', negated=True)
|
term = dict(operator='search', operand='"french fries"', negated=True)
|
||||||
self._do_add_term_test(term, 'WHERE NOT (search_pgroonga @@ :search_pgroonga_1)')
|
self._do_add_term_test(term, 'WHERE NOT (search_pgroonga @@ :search_pgroonga_1)')
|
||||||
|
|
||||||
def test_add_term_using_has_operator_and_attachment_operand(self):
|
def test_add_term_using_has_operator_and_attachment_operand(self):
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='has', operand='attachment')
|
term = dict(operator='has', operand='attachment')
|
||||||
self._do_add_term_test(term, 'WHERE has_attachment')
|
self._do_add_term_test(term, 'WHERE has_attachment')
|
||||||
|
|
||||||
def test_add_term_using_has_operator_attachment_operand_and_negated(self): # NEGATED
|
def test_add_term_using_has_operator_attachment_operand_and_negated(self): # NEGATED
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='has', operand='attachment', negated=True)
|
term = dict(operator='has', operand='attachment', negated=True)
|
||||||
self._do_add_term_test(term, 'WHERE NOT has_attachment')
|
self._do_add_term_test(term, 'WHERE NOT has_attachment')
|
||||||
|
|
||||||
def test_add_term_using_has_operator_and_image_operand(self):
|
def test_add_term_using_has_operator_and_image_operand(self):
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='has', operand='image')
|
term = dict(operator='has', operand='image')
|
||||||
self._do_add_term_test(term, 'WHERE has_image')
|
self._do_add_term_test(term, 'WHERE has_image')
|
||||||
|
|
||||||
def test_add_term_using_has_operator_image_operand_and_negated(self): # NEGATED
|
def test_add_term_using_has_operator_image_operand_and_negated(self): # NEGATED
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='has', operand='image', negated=True)
|
term = dict(operator='has', operand='image', negated=True)
|
||||||
self._do_add_term_test(term, 'WHERE NOT has_image')
|
self._do_add_term_test(term, 'WHERE NOT has_image')
|
||||||
|
|
||||||
def test_add_term_using_has_operator_and_link_operand(self):
|
def test_add_term_using_has_operator_and_link_operand(self):
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='has', operand='link')
|
term = dict(operator='has', operand='link')
|
||||||
self._do_add_term_test(term, 'WHERE has_link')
|
self._do_add_term_test(term, 'WHERE has_link')
|
||||||
|
|
||||||
def test_add_term_using_has_operator_link_operand_and_negated(self): # NEGATED
|
def test_add_term_using_has_operator_link_operand_and_negated(self): # NEGATED
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='has', operand='link', negated=True)
|
term = dict(operator='has', operand='link', negated=True)
|
||||||
self._do_add_term_test(term, 'WHERE NOT has_link')
|
self._do_add_term_test(term, 'WHERE NOT has_link')
|
||||||
|
|
||||||
def test_add_term_using_has_operator_non_supported_operand_should_raise_error(self):
|
def test_add_term_using_has_operator_non_supported_operand_should_raise_error(self):
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='has', operand='non_supported')
|
term = dict(operator='has', operand='non_supported')
|
||||||
self.assertRaises(BadNarrowOperator, self._build_query, term)
|
self.assertRaises(BadNarrowOperator, self._build_query, term)
|
||||||
|
|
||||||
def test_add_term_using_in_operator(self):
|
def test_add_term_using_in_operator(self):
|
||||||
|
# type: () -> None
|
||||||
mute_stream(self.realm, self.user_profile, 'Verona')
|
mute_stream(self.realm, self.user_profile, 'Verona')
|
||||||
term = dict(operator='in', operand='home')
|
term = dict(operator='in', operand='home')
|
||||||
self._do_add_term_test(term, 'WHERE recipient_id NOT IN (:recipient_id_1)')
|
self._do_add_term_test(term, 'WHERE recipient_id NOT IN (:recipient_id_1)')
|
||||||
|
|
||||||
def test_add_term_using_in_operator_and_negated(self):
|
def test_add_term_using_in_operator_and_negated(self):
|
||||||
|
# type: () -> None
|
||||||
# negated = True should not change anything
|
# negated = True should not change anything
|
||||||
mute_stream(self.realm, self.user_profile, 'Verona')
|
mute_stream(self.realm, self.user_profile, 'Verona')
|
||||||
term = dict(operator='in', operand='home', negated=True)
|
term = dict(operator='in', operand='home', negated=True)
|
||||||
self._do_add_term_test(term, 'WHERE recipient_id NOT IN (:recipient_id_1)')
|
self._do_add_term_test(term, 'WHERE recipient_id NOT IN (:recipient_id_1)')
|
||||||
|
|
||||||
def test_add_term_using_in_operator_and_all_operand(self):
|
def test_add_term_using_in_operator_and_all_operand(self):
|
||||||
|
# type: () -> None
|
||||||
mute_stream(self.realm, self.user_profile, 'Verona')
|
mute_stream(self.realm, self.user_profile, 'Verona')
|
||||||
term = dict(operator='in', operand='all')
|
term = dict(operator='in', operand='all')
|
||||||
query = self._build_query(term)
|
query = self._build_query(term)
|
||||||
self.assertEqual(str(query), 'SELECT id \nFROM zerver_message')
|
self.assertEqual(str(query), 'SELECT id \nFROM zerver_message')
|
||||||
|
|
||||||
def test_add_term_using_in_operator_all_operand_and_negated(self):
|
def test_add_term_using_in_operator_all_operand_and_negated(self):
|
||||||
|
# type: () -> None
|
||||||
# negated = True should not change anything
|
# negated = True should not change anything
|
||||||
mute_stream(self.realm, self.user_profile, 'Verona')
|
mute_stream(self.realm, self.user_profile, 'Verona')
|
||||||
term = dict(operator='in', operand='all', negated=True)
|
term = dict(operator='in', operand='all', negated=True)
|
||||||
@@ -245,22 +294,27 @@ class NarrowBuilderTest(ZulipTestCase):
|
|||||||
self.assertEqual(str(query), 'SELECT id \nFROM zerver_message')
|
self.assertEqual(str(query), 'SELECT id \nFROM zerver_message')
|
||||||
|
|
||||||
def test_add_term_using_in_operator_and_not_defined_operand(self):
|
def test_add_term_using_in_operator_and_not_defined_operand(self):
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='in', operand='not_defined')
|
term = dict(operator='in', operand='not_defined')
|
||||||
self.assertRaises(BadNarrowOperator, self._build_query, term)
|
self.assertRaises(BadNarrowOperator, self._build_query, term)
|
||||||
|
|
||||||
def test_add_term_using_near_operator(self):
|
def test_add_term_using_near_operator(self):
|
||||||
|
# type: () -> None
|
||||||
term = dict(operator='near', operand='operand')
|
term = dict(operator='near', operand='operand')
|
||||||
query = self._build_query(term)
|
query = self._build_query(term)
|
||||||
self.assertEqual(str(query), 'SELECT id \nFROM zerver_message')
|
self.assertEqual(str(query), 'SELECT id \nFROM zerver_message')
|
||||||
|
|
||||||
def _do_add_term_test(self, term, where_clause):
|
def _do_add_term_test(self, term, where_clause):
|
||||||
|
# type: (Dict[str, Any], Text) -> None
|
||||||
self.assertTrue(where_clause in str(self._build_query(term)))
|
self.assertTrue(where_clause in str(self._build_query(term)))
|
||||||
|
|
||||||
def _build_query(self, term):
|
def _build_query(self, term):
|
||||||
|
# type: (Dict[str, Any]) -> Query
|
||||||
return self.builder.add_term(self.raw_query, term)
|
return self.builder.add_term(self.raw_query, term)
|
||||||
|
|
||||||
class BuildNarrowFilterTest(TestCase):
|
class BuildNarrowFilterTest(TestCase):
|
||||||
def test_build_narrow_filter(self):
|
def test_build_narrow_filter(self):
|
||||||
|
# type: () -> None
|
||||||
fixtures_path = os.path.join(os.path.dirname(__file__),
|
fixtures_path = os.path.join(os.path.dirname(__file__),
|
||||||
'../fixtures/narrow.json')
|
'../fixtures/narrow.json')
|
||||||
scenarios = ujson.loads(open(fixtures_path, 'r').read())
|
scenarios = ujson.loads(open(fixtures_path, 'r').read())
|
||||||
@@ -277,6 +331,7 @@ class BuildNarrowFilterTest(TestCase):
|
|||||||
|
|
||||||
class IncludeHistoryTest(ZulipTestCase):
|
class IncludeHistoryTest(ZulipTestCase):
|
||||||
def test_ok_to_include_history(self):
|
def test_ok_to_include_history(self):
|
||||||
|
# type: () -> None
|
||||||
realm = get_realm_by_string_id('zulip')
|
realm = get_realm_by_string_id('zulip')
|
||||||
self.make_stream('public_stream', realm=realm)
|
self.make_stream('public_stream', realm=realm)
|
||||||
|
|
||||||
@@ -322,7 +377,8 @@ class IncludeHistoryTest(ZulipTestCase):
|
|||||||
class GetOldMessagesTest(ZulipTestCase):
|
class GetOldMessagesTest(ZulipTestCase):
|
||||||
|
|
||||||
def get_and_check_messages(self, modified_params):
|
def get_and_check_messages(self, modified_params):
|
||||||
post_params = {"anchor": 1, "num_before": 1, "num_after": 1}
|
# type: (Dict[str, Union[str, int]]) -> Dict[str, Dict]
|
||||||
|
post_params = {"anchor": 1, "num_before": 1, "num_after": 1} # type: Dict[str, Union[str, int]]
|
||||||
post_params.update(modified_params)
|
post_params.update(modified_params)
|
||||||
payload = self.client_get("/json/messages", dict(post_params))
|
payload = self.client_get("/json/messages", dict(post_params))
|
||||||
self.assert_json_success(payload)
|
self.assert_json_success(payload)
|
||||||
@@ -341,10 +397,11 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
def get_query_ids(self):
|
def get_query_ids(self):
|
||||||
|
# type: () -> Dict[Text, int]
|
||||||
hamlet_user = get_user_profile_by_email('hamlet@zulip.com')
|
hamlet_user = get_user_profile_by_email('hamlet@zulip.com')
|
||||||
othello_user = get_user_profile_by_email('othello@zulip.com')
|
othello_user = get_user_profile_by_email('othello@zulip.com')
|
||||||
|
|
||||||
query_ids = {}
|
query_ids = {} # type: Dict[Text, int]
|
||||||
|
|
||||||
scotland_stream = get_stream('Scotland', hamlet_user.realm)
|
scotland_stream = get_stream('Scotland', hamlet_user.realm)
|
||||||
query_ids['scotland_recipient'] = get_recipient(Recipient.STREAM, scotland_stream.id).id
|
query_ids['scotland_recipient'] = get_recipient(Recipient.STREAM, scotland_stream.id).id
|
||||||
@@ -356,6 +413,7 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
return query_ids
|
return query_ids
|
||||||
|
|
||||||
def test_successful_get_old_messages(self):
|
def test_successful_get_old_messages(self):
|
||||||
|
# type: () -> None
|
||||||
"""
|
"""
|
||||||
A call to GET /json/messages with valid parameters returns a list of
|
A call to GET /json/messages with valid parameters returns a list of
|
||||||
messages.
|
messages.
|
||||||
@@ -365,13 +423,12 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
|
|
||||||
# We have to support the legacy tuple style while there are old
|
# We have to support the legacy tuple style while there are old
|
||||||
# clients around, which might include third party home-grown bots.
|
# clients around, which might include third party home-grown bots.
|
||||||
narrow = [['pm-with', 'othello@zulip.com']]
|
self.get_and_check_messages(dict(narrow=ujson.dumps([['pm-with', 'othello@zulip.com']])))
|
||||||
self.get_and_check_messages(dict(narrow=ujson.dumps(narrow)))
|
|
||||||
|
|
||||||
narrow = [dict(operator='pm-with', operand='othello@zulip.com')]
|
self.get_and_check_messages(dict(narrow=ujson.dumps([dict(operator='pm-with', operand='othello@zulip.com')])))
|
||||||
self.get_and_check_messages(dict(narrow=ujson.dumps(narrow)))
|
|
||||||
|
|
||||||
def test_get_old_messages_with_narrow_pm_with(self):
|
def test_get_old_messages_with_narrow_pm_with(self):
|
||||||
|
# type: () -> None
|
||||||
"""
|
"""
|
||||||
A request for old messages with a narrow by pm-with only returns
|
A request for old messages with a narrow by pm-with only returns
|
||||||
conversations with that user.
|
conversations with that user.
|
||||||
@@ -379,6 +436,8 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
me = 'hamlet@zulip.com'
|
me = 'hamlet@zulip.com'
|
||||||
|
|
||||||
def dr_emails(dr):
|
def dr_emails(dr):
|
||||||
|
# type: (Union[Text, List[Dict[str, Any]]]) -> Text
|
||||||
|
assert isinstance(dr, list)
|
||||||
return ','.join(sorted(set([r['email'] for r in dr] + [me])))
|
return ','.join(sorted(set([r['email'] for r in dr] + [me])))
|
||||||
|
|
||||||
personals = [m for m in get_user_messages(get_user_profile_by_email(me))
|
personals = [m for m in get_user_messages(get_user_profile_by_email(me))
|
||||||
@@ -398,6 +457,7 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
self.assertEqual(dr_emails(message['display_recipient']), emails)
|
self.assertEqual(dr_emails(message['display_recipient']), emails)
|
||||||
|
|
||||||
def test_get_old_messages_with_narrow_stream(self):
|
def test_get_old_messages_with_narrow_stream(self):
|
||||||
|
# type: () -> None
|
||||||
"""
|
"""
|
||||||
A request for old messages with a narrow by stream only returns
|
A request for old messages with a narrow by stream only returns
|
||||||
messages for that stream.
|
messages for that stream.
|
||||||
@@ -421,6 +481,7 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
self.assertEqual(message["recipient_id"], stream_id)
|
self.assertEqual(message["recipient_id"], stream_id)
|
||||||
|
|
||||||
def test_get_old_messages_with_narrow_stream_mit_unicode_regex(self):
|
def test_get_old_messages_with_narrow_stream_mit_unicode_regex(self):
|
||||||
|
# type: () -> None
|
||||||
"""
|
"""
|
||||||
A request for old messages for a user in the mit.edu relam with unicode
|
A request for old messages for a user in the mit.edu relam with unicode
|
||||||
stream name should be correctly escaped in the database query.
|
stream name should be correctly escaped in the database query.
|
||||||
@@ -452,6 +513,7 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
self.assertEqual(message["recipient_id"], stream_id)
|
self.assertEqual(message["recipient_id"], stream_id)
|
||||||
|
|
||||||
def test_get_old_messages_with_narrow_topic_mit_unicode_regex(self):
|
def test_get_old_messages_with_narrow_topic_mit_unicode_regex(self):
|
||||||
|
# type: () -> None
|
||||||
"""
|
"""
|
||||||
A request for old messages for a user in the mit.edu relam with unicode
|
A request for old messages for a user in the mit.edu relam with unicode
|
||||||
topic name should be correctly escaped in the database query.
|
topic name should be correctly escaped in the database query.
|
||||||
@@ -481,6 +543,7 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
self.assertEqual(message["recipient_id"], stream_id)
|
self.assertEqual(message["recipient_id"], stream_id)
|
||||||
|
|
||||||
def test_get_old_messages_with_narrow_sender(self):
|
def test_get_old_messages_with_narrow_sender(self):
|
||||||
|
# type: () -> None
|
||||||
"""
|
"""
|
||||||
A request for old messages with a narrow by sender only returns
|
A request for old messages with a narrow by sender only returns
|
||||||
messages sent by that person.
|
messages sent by that person.
|
||||||
@@ -519,7 +582,7 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
self.login(email)
|
self.login(email)
|
||||||
|
|
||||||
def send(content):
|
def send(content):
|
||||||
# type: (Text) -> None
|
# type: (Text) -> int
|
||||||
msg_id = self.send_message(
|
msg_id = self.send_message(
|
||||||
sender_name=email,
|
sender_name=email,
|
||||||
raw_recipients="Verona",
|
raw_recipients="Verona",
|
||||||
@@ -551,6 +614,7 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
|
|
||||||
@override_settings(USING_PGROONGA=False)
|
@override_settings(USING_PGROONGA=False)
|
||||||
def test_get_old_messages_with_search(self):
|
def test_get_old_messages_with_search(self):
|
||||||
|
# type: () -> None
|
||||||
self.login("cordelia@zulip.com")
|
self.login("cordelia@zulip.com")
|
||||||
|
|
||||||
messages_to_search = [
|
messages_to_search = [
|
||||||
@@ -580,7 +644,7 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
narrow=ujson.dumps(narrow),
|
narrow=ujson.dumps(narrow),
|
||||||
anchor=0,
|
anchor=0,
|
||||||
num_after=10,
|
num_after=10,
|
||||||
))
|
)) # type: Dict[str, Dict]
|
||||||
self.assertEqual(len(result['messages']), 2)
|
self.assertEqual(len(result['messages']), 2)
|
||||||
messages = result['messages']
|
messages = result['messages']
|
||||||
|
|
||||||
@@ -603,6 +667,7 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
|
|
||||||
@override_settings(USING_PGROONGA=True)
|
@override_settings(USING_PGROONGA=True)
|
||||||
def test_get_old_messages_with_search_pgroonga(self):
|
def test_get_old_messages_with_search_pgroonga(self):
|
||||||
|
# type: () -> None
|
||||||
self.login("cordelia@zulip.com")
|
self.login("cordelia@zulip.com")
|
||||||
|
|
||||||
messages_to_search = [
|
messages_to_search = [
|
||||||
@@ -639,7 +704,7 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
narrow=ujson.dumps(narrow),
|
narrow=ujson.dumps(narrow),
|
||||||
anchor=0,
|
anchor=0,
|
||||||
num_after=10,
|
num_after=10,
|
||||||
))
|
)) # type: Dict[str, Dict]
|
||||||
self.assertEqual(len(result['messages']), 4)
|
self.assertEqual(len(result['messages']), 4)
|
||||||
messages = result['messages']
|
messages = result['messages']
|
||||||
|
|
||||||
@@ -661,6 +726,7 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
u'<p>I want to go to <span class="highlight">日本</span>!</p>')
|
u'<p>I want to go to <span class="highlight">日本</span>!</p>')
|
||||||
|
|
||||||
def test_get_old_messages_with_only_searching_anchor(self):
|
def test_get_old_messages_with_only_searching_anchor(self):
|
||||||
|
# type: () -> None
|
||||||
"""
|
"""
|
||||||
Test that specifying an anchor but 0 for num_before and num_after
|
Test that specifying an anchor but 0 for num_before and num_after
|
||||||
returns at most 1 message.
|
returns at most 1 message.
|
||||||
@@ -671,7 +737,7 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
narrow = [dict(operator='sender', operand='cordelia@zulip.com')]
|
narrow = [dict(operator='sender', operand='cordelia@zulip.com')]
|
||||||
result = self.get_and_check_messages(dict(narrow=ujson.dumps(narrow),
|
result = self.get_and_check_messages(dict(narrow=ujson.dumps(narrow),
|
||||||
anchor=anchor, num_before=0,
|
anchor=anchor, num_before=0,
|
||||||
num_after=0))
|
num_after=0)) # type: Dict[str, Dict]
|
||||||
self.assertEqual(len(result['messages']), 1)
|
self.assertEqual(len(result['messages']), 1)
|
||||||
|
|
||||||
narrow = [dict(operator='is', operand='mentioned')]
|
narrow = [dict(operator='is', operand='mentioned')]
|
||||||
@@ -681,13 +747,14 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
self.assertEqual(len(result['messages']), 0)
|
self.assertEqual(len(result['messages']), 0)
|
||||||
|
|
||||||
def test_missing_params(self):
|
def test_missing_params(self):
|
||||||
|
# type: () -> None
|
||||||
"""
|
"""
|
||||||
anchor, num_before, and num_after are all required
|
anchor, num_before, and num_after are all required
|
||||||
POST parameters for get_old_messages.
|
POST parameters for get_old_messages.
|
||||||
"""
|
"""
|
||||||
self.login("hamlet@zulip.com")
|
self.login("hamlet@zulip.com")
|
||||||
|
|
||||||
required_args = (("anchor", 1), ("num_before", 1), ("num_after", 1))
|
required_args = (("anchor", 1), ("num_before", 1), ("num_after", 1)) # type: Tuple[Tuple[Text, int], ...]
|
||||||
|
|
||||||
for i in range(len(required_args)):
|
for i in range(len(required_args)):
|
||||||
post_params = dict(required_args[:i] + required_args[i + 1:])
|
post_params = dict(required_args[:i] + required_args[i + 1:])
|
||||||
@@ -696,6 +763,7 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
"Missing '%s' argument" % (required_args[i][0],))
|
"Missing '%s' argument" % (required_args[i][0],))
|
||||||
|
|
||||||
def test_bad_int_params(self):
|
def test_bad_int_params(self):
|
||||||
|
# type: () -> None
|
||||||
"""
|
"""
|
||||||
num_before, num_after, and narrow must all be non-negative
|
num_before, num_after, and narrow must all be non-negative
|
||||||
integers or strings that can be converted to non-negative integers.
|
integers or strings that can be converted to non-negative integers.
|
||||||
@@ -719,15 +787,16 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
"Bad value for '%s': %s" % (param, type))
|
"Bad value for '%s': %s" % (param, type))
|
||||||
|
|
||||||
def test_bad_narrow_type(self):
|
def test_bad_narrow_type(self):
|
||||||
|
# type: () -> None
|
||||||
"""
|
"""
|
||||||
narrow must be a list of string pairs.
|
narrow must be a list of string pairs.
|
||||||
"""
|
"""
|
||||||
self.login("hamlet@zulip.com")
|
self.login("hamlet@zulip.com")
|
||||||
|
|
||||||
other_params = [("anchor", 0), ("num_before", 0), ("num_after", 0)]
|
other_params = [("anchor", 0), ("num_before", 0), ("num_after", 0)] # type: list[Tuple[Text, Union[int, str, bool]]]
|
||||||
|
|
||||||
bad_types = (False, 0, '', '{malformed json,',
|
bad_types = (False, 0, '', '{malformed json,',
|
||||||
'{foo: 3}', '[1,2]', '[["x","y","z"]]')
|
'{foo: 3}', '[1,2]', '[["x","y","z"]]') # type: Tuple[Union[int, str, bool], ...]
|
||||||
for type in bad_types:
|
for type in bad_types:
|
||||||
post_params = dict(other_params + [("narrow", type)])
|
post_params = dict(other_params + [("narrow", type)])
|
||||||
result = self.client_get("/json/messages", post_params)
|
result = self.client_get("/json/messages", post_params)
|
||||||
@@ -735,16 +804,18 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
"Bad value for 'narrow': %s" % (type,))
|
"Bad value for 'narrow': %s" % (type,))
|
||||||
|
|
||||||
def test_old_empty_narrow(self):
|
def test_old_empty_narrow(self):
|
||||||
|
# type: () -> None
|
||||||
"""
|
"""
|
||||||
'{}' is accepted to mean 'no narrow', for use by old mobile clients.
|
'{}' is accepted to mean 'no narrow', for use by old mobile clients.
|
||||||
"""
|
"""
|
||||||
self.login("hamlet@zulip.com")
|
self.login("hamlet@zulip.com")
|
||||||
all_result = self.get_and_check_messages({})
|
all_result = self.get_and_check_messages({}) # type: Dict[str, Dict]
|
||||||
narrow_result = self.get_and_check_messages({'narrow': '{}'})
|
narrow_result = self.get_and_check_messages({'narrow': '{}'}) # type: Dict[str, Dict]
|
||||||
|
|
||||||
self.assertEqual(message_ids(all_result), message_ids(narrow_result))
|
self.assertEqual(message_ids(all_result), message_ids(narrow_result))
|
||||||
|
|
||||||
def test_bad_narrow_operator(self):
|
def test_bad_narrow_operator(self):
|
||||||
|
# type: () -> None
|
||||||
"""
|
"""
|
||||||
Unrecognized narrow operators are rejected.
|
Unrecognized narrow operators are rejected.
|
||||||
"""
|
"""
|
||||||
@@ -757,6 +828,7 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
"Invalid narrow operator: unknown operator")
|
"Invalid narrow operator: unknown operator")
|
||||||
|
|
||||||
def test_non_string_narrow_operand_in_dict(self):
|
def test_non_string_narrow_operand_in_dict(self):
|
||||||
|
# type: () -> None
|
||||||
"""
|
"""
|
||||||
We expect search operands to be strings, not integers.
|
We expect search operands to be strings, not integers.
|
||||||
"""
|
"""
|
||||||
@@ -768,7 +840,8 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
self.assert_json_error_contains(result, 'elem["operand"] is not a string')
|
self.assert_json_error_contains(result, 'elem["operand"] is not a string')
|
||||||
|
|
||||||
def exercise_bad_narrow_operand(self, operator, operands, error_msg):
|
def exercise_bad_narrow_operand(self, operator, operands, error_msg):
|
||||||
other_params = [("anchor", 0), ("num_before", 0), ("num_after", 0)]
|
# type: (Text, Sequence, Text) -> None
|
||||||
|
other_params = [("anchor", 0), ("num_before", 0), ("num_after", 0)] # type: List
|
||||||
for operand in operands:
|
for operand in operands:
|
||||||
post_params = dict(other_params + [
|
post_params = dict(other_params + [
|
||||||
("narrow", ujson.dumps([[operator, operand]]))])
|
("narrow", ujson.dumps([[operator, operand]]))])
|
||||||
@@ -776,36 +849,41 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
self.assert_json_error_contains(result, error_msg)
|
self.assert_json_error_contains(result, error_msg)
|
||||||
|
|
||||||
def test_bad_narrow_stream_content(self):
|
def test_bad_narrow_stream_content(self):
|
||||||
|
# type: () -> None
|
||||||
"""
|
"""
|
||||||
If an invalid stream name is requested in get_old_messages, an error is
|
If an invalid stream name is requested in get_old_messages, an error is
|
||||||
returned.
|
returned.
|
||||||
"""
|
"""
|
||||||
self.login("hamlet@zulip.com")
|
self.login("hamlet@zulip.com")
|
||||||
bad_stream_content = (0, [], ["x", "y"])
|
bad_stream_content = (0, [], ["x", "y"]) # type: Sequence
|
||||||
self.exercise_bad_narrow_operand("stream", bad_stream_content,
|
self.exercise_bad_narrow_operand("stream", bad_stream_content,
|
||||||
"Bad value for 'narrow'")
|
"Bad value for 'narrow'")
|
||||||
|
|
||||||
def test_bad_narrow_one_on_one_email_content(self):
|
def test_bad_narrow_one_on_one_email_content(self):
|
||||||
|
# type: () -> None
|
||||||
"""
|
"""
|
||||||
If an invalid 'pm-with' is requested in get_old_messages, an
|
If an invalid 'pm-with' is requested in get_old_messages, an
|
||||||
error is returned.
|
error is returned.
|
||||||
"""
|
"""
|
||||||
self.login("hamlet@zulip.com")
|
self.login("hamlet@zulip.com")
|
||||||
bad_stream_content = (0, [], ["x", "y"])
|
bad_stream_content = (0, [], ["x", "y"]) # type: Tuple[int, List[None], List[Text]]
|
||||||
self.exercise_bad_narrow_operand("pm-with", bad_stream_content,
|
self.exercise_bad_narrow_operand("pm-with", bad_stream_content,
|
||||||
"Bad value for 'narrow'")
|
"Bad value for 'narrow'")
|
||||||
|
|
||||||
def test_bad_narrow_nonexistent_stream(self):
|
def test_bad_narrow_nonexistent_stream(self):
|
||||||
|
# type: () -> None
|
||||||
self.login("hamlet@zulip.com")
|
self.login("hamlet@zulip.com")
|
||||||
self.exercise_bad_narrow_operand("stream", ['non-existent stream'],
|
self.exercise_bad_narrow_operand("stream", ['non-existent stream'],
|
||||||
"Invalid narrow operator: unknown stream")
|
"Invalid narrow operator: unknown stream")
|
||||||
|
|
||||||
def test_bad_narrow_nonexistent_email(self):
|
def test_bad_narrow_nonexistent_email(self):
|
||||||
|
# type: () -> None
|
||||||
self.login("hamlet@zulip.com")
|
self.login("hamlet@zulip.com")
|
||||||
self.exercise_bad_narrow_operand("pm-with", ['non-existent-user@zulip.com'],
|
self.exercise_bad_narrow_operand("pm-with", ['non-existent-user@zulip.com'],
|
||||||
"Invalid narrow operator: unknown user")
|
"Invalid narrow operator: unknown user")
|
||||||
|
|
||||||
def test_message_without_rendered_content(self):
|
def test_message_without_rendered_content(self):
|
||||||
|
# type: () -> None
|
||||||
"""Older messages may not have rendered_content in the database"""
|
"""Older messages may not have rendered_content in the database"""
|
||||||
m = self.get_last_message()
|
m = self.get_last_message()
|
||||||
m.rendered_content = m.rendered_content_version = None
|
m.rendered_content = m.rendered_content_version = None
|
||||||
@@ -815,6 +893,7 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
self.assertEqual(d['content'], '<p>test content</p>')
|
self.assertEqual(d['content'], '<p>test content</p>')
|
||||||
|
|
||||||
def common_check_get_old_messages_query(self, query_params, expected):
|
def common_check_get_old_messages_query(self, query_params, expected):
|
||||||
|
# type: (Dict[str, object], Text) -> None
|
||||||
user_profile = get_user_profile_by_email("hamlet@zulip.com")
|
user_profile = get_user_profile_by_email("hamlet@zulip.com")
|
||||||
request = POSTRequestMock(query_params, user_profile)
|
request = POSTRequestMock(query_params, user_profile)
|
||||||
with queries_captured() as queries:
|
with queries_captured() as queries:
|
||||||
@@ -822,12 +901,13 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
|
|
||||||
for query in queries:
|
for query in queries:
|
||||||
if "/* get_old_messages */" in query['sql']:
|
if "/* get_old_messages */" in query['sql']:
|
||||||
sql = query['sql'].replace(" /* get_old_messages */", '')
|
sql = str(query['sql']).replace(" /* get_old_messages */", '')
|
||||||
self.assertEqual(sql, expected)
|
self.assertEqual(sql, expected)
|
||||||
return
|
return
|
||||||
self.fail("get_old_messages query not found")
|
self.fail("get_old_messages query not found")
|
||||||
|
|
||||||
def test_use_first_unread_anchor_with_some_unread_messages(self):
|
def test_use_first_unread_anchor_with_some_unread_messages(self):
|
||||||
|
# type: () -> None
|
||||||
user_profile = get_user_profile_by_email("hamlet@zulip.com")
|
user_profile = get_user_profile_by_email("hamlet@zulip.com")
|
||||||
|
|
||||||
# Have Othello send messages to Hamlet that he hasn't read.
|
# Have Othello send messages to Hamlet that he hasn't read.
|
||||||
@@ -862,6 +942,7 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
self.assertIn(cond, sql)
|
self.assertIn(cond, sql)
|
||||||
|
|
||||||
def test_use_first_unread_anchor_with_no_unread_messages(self):
|
def test_use_first_unread_anchor_with_no_unread_messages(self):
|
||||||
|
# type: () -> None
|
||||||
user_profile = get_user_profile_by_email("hamlet@zulip.com")
|
user_profile = get_user_profile_by_email("hamlet@zulip.com")
|
||||||
|
|
||||||
query_params = dict(
|
query_params = dict(
|
||||||
@@ -883,6 +964,7 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
self.assertIn('AND message_id = 10000000000000000', queries[0]['sql'])
|
self.assertIn('AND message_id = 10000000000000000', queries[0]['sql'])
|
||||||
|
|
||||||
def test_use_first_unread_anchor_with_muted_topics(self):
|
def test_use_first_unread_anchor_with_muted_topics(self):
|
||||||
|
# type: () -> None
|
||||||
"""
|
"""
|
||||||
Test that our logic related to `use_first_unread_anchor`
|
Test that our logic related to `use_first_unread_anchor`
|
||||||
invokes the `message_id = 10000000000000000` hack for
|
invokes the `message_id = 10000000000000000` hack for
|
||||||
@@ -915,7 +997,7 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
|
|
||||||
# Do some tests on the main query, to verify the muting logic
|
# Do some tests on the main query, to verify the muting logic
|
||||||
# runs on this code path.
|
# runs on this code path.
|
||||||
queries = [q for q in all_queries if q['sql'].startswith("SELECT message_id, flags")]
|
queries = [q for q in all_queries if str(q['sql']).startswith("SELECT message_id, flags")]
|
||||||
self.assertEqual(len(queries), 1)
|
self.assertEqual(len(queries), 1)
|
||||||
|
|
||||||
stream = get_stream('Scotland', realm)
|
stream = get_stream('Scotland', realm)
|
||||||
@@ -930,6 +1012,7 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
self.assertIn('AND message_id = 10000000000000000', queries[0]['sql'])
|
self.assertIn('AND message_id = 10000000000000000', queries[0]['sql'])
|
||||||
|
|
||||||
def test_exclude_muting_conditions(self):
|
def test_exclude_muting_conditions(self):
|
||||||
|
# type: () -> None
|
||||||
realm = get_realm_by_string_id('zulip')
|
realm = get_realm_by_string_id('zulip')
|
||||||
self.make_stream('web stuff')
|
self.make_stream('web stuff')
|
||||||
user_profile = get_user_profile_by_email("hamlet@zulip.com")
|
user_profile = get_user_profile_by_email("hamlet@zulip.com")
|
||||||
@@ -991,6 +1074,7 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
self.assertEqual(params['upper_2'], 'css')
|
self.assertEqual(params['upper_2'], 'css')
|
||||||
|
|
||||||
def test_get_old_messages_queries(self):
|
def test_get_old_messages_queries(self):
|
||||||
|
# type: () -> None
|
||||||
query_ids = self.get_query_ids()
|
query_ids = self.get_query_ids()
|
||||||
|
|
||||||
sql_template = 'SELECT anon_1.message_id, anon_1.flags \nFROM (SELECT message_id, flags \nFROM zerver_usermessage \nWHERE user_profile_id = {hamlet_id} AND message_id >= 0 ORDER BY message_id ASC \n LIMIT 11) AS anon_1 ORDER BY message_id ASC'
|
sql_template = 'SELECT anon_1.message_id, anon_1.flags \nFROM (SELECT message_id, flags \nFROM zerver_usermessage \nWHERE user_profile_id = {hamlet_id} AND message_id >= 0 ORDER BY message_id ASC \n LIMIT 11) AS anon_1 ORDER BY message_id ASC'
|
||||||
@@ -1006,6 +1090,7 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
self.common_check_get_old_messages_query({'anchor': 100, 'num_before': 10, 'num_after': 10}, sql)
|
self.common_check_get_old_messages_query({'anchor': 100, 'num_before': 10, 'num_after': 10}, sql)
|
||||||
|
|
||||||
def test_get_old_messages_with_narrow_queries(self):
|
def test_get_old_messages_with_narrow_queries(self):
|
||||||
|
# type: () -> None
|
||||||
query_ids = self.get_query_ids()
|
query_ids = self.get_query_ids()
|
||||||
|
|
||||||
sql_template = 'SELECT anon_1.message_id, anon_1.flags \nFROM (SELECT message_id, flags \nFROM zerver_usermessage JOIN zerver_message ON zerver_usermessage.message_id = zerver_message.id \nWHERE user_profile_id = {hamlet_id} AND (sender_id = {othello_id} AND recipient_id = {hamlet_recipient} OR sender_id = {hamlet_id} AND recipient_id = {othello_recipient}) AND message_id >= 0 ORDER BY message_id ASC \n LIMIT 10) AS anon_1 ORDER BY message_id ASC'
|
sql_template = 'SELECT anon_1.message_id, anon_1.flags \nFROM (SELECT message_id, flags \nFROM zerver_usermessage JOIN zerver_message ON zerver_usermessage.message_id = zerver_message.id \nWHERE user_profile_id = {hamlet_id} AND (sender_id = {othello_id} AND recipient_id = {hamlet_recipient} OR sender_id = {hamlet_id} AND recipient_id = {othello_recipient}) AND message_id >= 0 ORDER BY message_id ASC \n LIMIT 10) AS anon_1 ORDER BY message_id ASC'
|
||||||
@@ -1059,9 +1144,10 @@ class GetOldMessagesTest(ZulipTestCase):
|
|||||||
|
|
||||||
@override_settings(USING_PGROONGA=False)
|
@override_settings(USING_PGROONGA=False)
|
||||||
def test_get_old_messages_with_search_queries(self):
|
def test_get_old_messages_with_search_queries(self):
|
||||||
|
# type: () -> None
|
||||||
query_ids = self.get_query_ids()
|
query_ids = self.get_query_ids()
|
||||||
|
|
||||||
sql_template = "SELECT anon_1.message_id, anon_1.flags, anon_1.subject, anon_1.rendered_content, anon_1.content_matches, anon_1.subject_matches \nFROM (SELECT message_id, flags, subject, rendered_content, ts_match_locs_array('zulip.english_us_search', rendered_content, plainto_tsquery('zulip.english_us_search', 'jumping')) AS content_matches, ts_match_locs_array('zulip.english_us_search', escape_html(subject), plainto_tsquery('zulip.english_us_search', 'jumping')) AS subject_matches \nFROM zerver_usermessage JOIN zerver_message ON zerver_usermessage.message_id = zerver_message.id \nWHERE user_profile_id = {hamlet_id} AND (search_tsvector @@ plainto_tsquery('zulip.english_us_search', 'jumping')) AND message_id >= 0 ORDER BY message_id ASC \n LIMIT 10) AS anon_1 ORDER BY message_id ASC"
|
sql_template = "SELECT anon_1.message_id, anon_1.flags, anon_1.subject, anon_1.rendered_content, anon_1.content_matches, anon_1.subject_matches \nFROM (SELECT message_id, flags, subject, rendered_content, ts_match_locs_array('zulip.english_us_search', rendered_content, plainto_tsquery('zulip.english_us_search', 'jumping')) AS content_matches, ts_match_locs_array('zulip.english_us_search', escape_html(subject), plainto_tsquery('zulip.english_us_search', 'jumping')) AS subject_matches \nFROM zerver_usermessage JOIN zerver_message ON zerver_usermessage.message_id = zerver_message.id \nWHERE user_profile_id = {hamlet_id} AND (search_tsvector @@ plainto_tsquery('zulip.english_us_search', 'jumping')) AND message_id >= 0 ORDER BY message_id ASC \n LIMIT 10) AS anon_1 ORDER BY message_id ASC" # type: Text
|
||||||
sql = sql_template.format(**query_ids)
|
sql = sql_template.format(**query_ids)
|
||||||
self.common_check_get_old_messages_query({'anchor': 0, 'num_before': 0, 'num_after': 10,
|
self.common_check_get_old_messages_query({'anchor': 0, 'num_before': 0, 'num_after': 10,
|
||||||
'narrow': '[["search", "jumping"]]'},
|
'narrow': '[["search", "jumping"]]'},
|
||||||
|
|||||||
Reference in New Issue
Block a user