Example #1
0
def test_search_queries_for_replies(query):
    """It should do a second query for replies to the results of the first."""
    request = dummy_request()

    # Mock the Builder objects that Builder() returns.
    builder = mock.Mock()
    query.Builder.side_effect = [
        mock.Mock(),  # We don't care about the first Builder in this test.
        builder
    ]

    # Mock the search results.
    request.es.conn.search.side_effect = [
        # The first time search() is called it returns the result of querying
        # for the top-level annotations only.
        dummy_search_results(count=3),
        # The second call returns the result of querying for all the replies to
        # those annotations
        dummy_search_results(start=4, count=3, name='reply'),
    ]

    core.search(request, {}, separate_replies=True)

    # It should construct a RepliesMatcher for replies to the annotations from
    # the first search.
    query.RepliesMatcher.assert_called_once_with(['id_1', 'id_2', 'id_3'])

    # It should append the RepliesMatcher to the query builder.
    builder.append_matcher.assert_called_with(query.RepliesMatcher.return_value)

    # It should call search() a second time with the body from the
    # query builder.
    assert request.es.conn.search.call_count == 2
    _, last_call_kwargs = request.es.conn.search.call_args_list[-1]
    assert last_call_kwargs['body'] == builder.build.return_value
Example #2
0
def test_search_logs_a_warning_if_there_are_too_many_replies(models, log):
    """It should log a warning if there's more than one page of replies."""
    models.Annotation.search_raw.side_effect = [
        {
            'hits': {
                'total': 3,
                'hits': [
                    {'_id': 'annotation_{n}'.format(n=n), '_source': 'source'}
                    for n in range(0, 3)]
            }
        },
        # The second call to search_raw() returns 'total': 11000 but only
        # returns the first 100 of 11000 hits.
        {
            'hits': {
                'total': 11000,
                'hits': [
                    {'_id': 'reply_{n}'.format(n=n), '_source': 'source'}
                    for n in range(0, 100)]
            }
        },
    ]

    core.search(mock.Mock(), mock.Mock(), separate_replies=True)

    assert log.warn.call_count == 1
Example #3
0
def test_search_does_not_log_a_warning_if_there_are_not_too_many_replies(
        models, log):
    """It should not log a warning if there's less than one page of replies."""
    models.Annotation.search_raw.side_effect = [
        {
            'hits': {
                'total':
                3,
                'hits': [{
                    '_id': 'annotation_{n}'.format(n=n),
                    '_source': 'source'
                } for n in range(0, 3)]
            }
        },
        # The second call to search_raw() returns 'total': 100 and returns all
        # 100 hits in the first page pf results.
        {
            'hits': {
                'total':
                100,
                'hits': [{
                    '_id': 'reply_{n}'.format(n=n),
                    '_source': 'source'
                } for n in range(0, 100)]
            }
        },
    ]

    core.search(mock.Mock(), mock.Mock(), separate_replies=True)

    assert not log.warn.called
Example #4
0
def test_search_logs_a_warning_if_there_are_too_many_replies(models, log):
    """It should log a warning if there's more than one page of replies."""
    models.Annotation.search_raw.side_effect = [
        {
            'hits': {
                'total':
                3,
                'hits': [{
                    '_id': 'annotation_{n}'.format(n=n),
                    '_source': 'source'
                } for n in range(0, 3)]
            }
        },
        # The second call to search_raw() returns 'total': 11000 but only
        # returns the first 100 of 11000 hits.
        {
            'hits': {
                'total':
                11000,
                'hits': [{
                    '_id': 'reply_{n}'.format(n=n),
                    '_source': 'source'
                } for n in range(0, 100)]
            }
        },
    ]

    core.search(mock.Mock(), mock.Mock(), separate_replies=True)

    assert log.warn.call_count == 1
Example #5
0
def test_search_does_not_log_a_warning_if_there_are_not_too_many_replies(
        models, log):
    """It should not log a warning if there's less than one page of replies."""
    models.Annotation.search_raw.side_effect = [
        {
            'hits': {
                'total': 3,
                'hits': [
                    {'_id': 'annotation_{n}'.format(n=n), '_source': 'source'}
                    for n in range(0, 3)]
            }
        },
        # The second call to search_raw() returns 'total': 100 and returns all
        # 100 hits in the first page pf results.
        {
            'hits': {
                'total': 100,
                'hits': [
                    {'_id': 'reply_{n}'.format(n=n), '_source': 'source'}
                    for n in range(0, 100)]
            }
        },
    ]

    core.search(mock.Mock(), mock.Mock(), separate_replies=True)

    assert not log.warn.called
Example #6
0
def test_search_does_not_log_a_warning_if_there_are_not_too_many_replies(log, pyramid_request):
    """It should not log a warning if there's less than one page of replies."""
    pyramid_request.es.conn.search.side_effect = [
        dummy_search_results(count=3),
        dummy_search_results(count=100, start=4, name='reply'),
    ]

    core.search(pyramid_request, {}, separate_replies=True)

    assert not log.warn.called
Example #7
0
def test_search_queries_for_replies(query, models):
    """It should do a second query for replies to the results of the first."""
    # Mock the Builder objects that Builder() returns.
    builder = mock.Mock()
    query.Builder.side_effect = [
        mock.Mock(),  # We don't care about the first Builder in this test.
        builder
    ]

    # Mock the search results that search_raw() returns.
    models.Annotation.search_raw.side_effect = [
        # The first time search_raw() is called it returns the result of
        # querying for the top-level annotations only.
        {
            'hits': {
                'total': 3,
                'hits': [
                    {'_id': 'annotation_1', '_source': 'source'},
                    {'_id': 'annotation_2', '_source': 'source'},
                    {'_id': 'annotation_3', '_source': 'source'}
                ]
            }
        },
        # The second call returns the result of querying for all the replies to
        # those annotations
        {
            'hits': {
                'total': 3,
                'hits': [
                    {'_id': 'reply_1', '_source': 'source'},
                    {'_id': 'reply_2', '_source': 'source'},
                    {'_id': 'reply_3', '_source': 'source'}
                ]
            }
        },
    ]

    core.search(mock.Mock(), mock.Mock(), separate_replies=True)

    # It should construct a RepliesMatcher for replies to the annotations from
    # the first search.
    query.RepliesMatcher.assert_called_once_with(
        ['annotation_1', 'annotation_2', 'annotation_3'])

    # It should append the RepliesMatcher to the query builder.
    assert builder.append_matcher.call_args_list[-1] == mock.call(
        query.RepliesMatcher.return_value)

    # It should call search_raw() a second time with the body from the
    # query builder.
    assert models.Annotation.search_raw.call_count == 2
    last_call = models.Annotation.search_raw.call_args_list[-1]
    first_arg = last_call[0][0]
    assert first_arg == builder.build.return_value
Example #8
0
def test_search_does_not_log_a_warning_if_there_are_not_too_many_replies(log):
    """It should not log a warning if there's less than one page of replies."""
    request = dummy_request()
    request.es.conn.search.side_effect = [
        dummy_search_results(count=3),
        dummy_search_results(count=100, start=4, name='reply'),
    ]

    core.search(request, {}, separate_replies=True)

    assert not log.warn.called
Example #9
0
def test_search_logs_a_warning_if_there_are_too_many_replies(log, pyramid_request):
    """It should log a warning if there's more than one page of replies."""
    parent_results = dummy_search_results(count=3)
    replies_results = dummy_search_results(count=100, name='reply')
    # The second call to search() returns 'total': 11000 but only returns
    # the first 100 of 11000 hits.
    replies_results['hits']['total'] = 11000
    pyramid_request.es.conn.search.side_effect = [parent_results, replies_results]

    core.search(pyramid_request, {}, separate_replies=True)

    assert log.warn.call_count == 1
Example #10
0
def test_search_logs_a_warning_if_there_are_too_many_replies(log):
    """It should log a warning if there's more than one page of replies."""
    request = dummy_request()
    parent_results = dummy_search_results(count=3)
    replies_results = dummy_search_results(count=100, name='reply')
    # The second call to search() returns 'total': 11000 but only returns
    # the first 100 of 11000 hits.
    replies_results['hits']['total'] = 11000
    request.es.conn.search.side_effect = [parent_results, replies_results]

    core.search(request, {}, separate_replies=True)

    assert log.warn.call_count == 1
Example #11
0
def test_search_with_user_object(_, search_raw):
    """If search() gets a user arg it passes it to search_raw().

    Note: This test is testing the function's user param. You can also
    pass one or more user arguments in the request.params, those are
    tested elsewhere.

    """
    user = mock.MagicMock()

    core.search(request_params=multidict.NestedMultiDict(), user=user)

    first_call = search_raw.call_args_list[0]
    assert first_call[1]["user"] == user
Example #12
0
def test_search_with_user_object(models):
    """If search() gets a user arg it passes it to search_raw().

    Note: This test is testing the function's user param. You can also
    pass one or more user arguments in the request.params, those are
    tested elsewhere.

    """
    user = mock.MagicMock()

    core.search(request_params=multidict.NestedMultiDict(), user=user)

    first_call = models.Annotation.search_raw.call_args_list[0]
    assert first_call[1]["user"] == user
Example #13
0
def test_search_returns_replies():
    """It should return an annotation dict for each reply from search()."""
    request = dummy_request()
    request.es.conn.search.side_effect = [
        # The first time search() is called it returns the result of querying
        # for the top-level annotations only.
        dummy_search_results(count=1),
        # The second call returns the result of querying for all the replies to
        # those annotations
        dummy_search_results(start=2, count=3, name='reply'),
    ]

    result = core.search(request, {}, separate_replies=True)

    assert result['replies'] == [
        {
            'name': 'reply_2',
            'id': 'id_2'
        },
        {
            'name': 'reply_3',
            'id': 'id_3'
        },
        {
            'name': 'reply_4',
            'id': 'id_4'
        },
    ]
Example #14
0
def test_search_does_not_exclude_replies(query):
    result = core.search(mock.Mock(), mock.Mock())

    assert not query.TopLevelAnnotationsFilter.called, (
        "Replies should not be filtered out of the 'rows' list if "
        "separate_replies=True is not given")
    assert 'replies' not in result, (
        "The separate 'replies' list should not be included in the result if "
        "separate_replies=True is not given")
Example #15
0
def test_search_does_not_exclude_replies(query):
    result = core.search(mock.Mock(), mock.Mock())

    assert not query.TopLevelAnnotationsFilter.called, (
        "Replies should not be filtered out of the 'rows' list if "
        "separate_replies=True is not given")
    assert 'replies' not in result, (
        "The separate 'replies' list should not be included in the result if "
        "separate_replies=True is not given")
Example #16
0
def test_search_returns_replies(models):
    """It should return an Annotation for each reply from search_raw()."""
    models.Annotation.search_raw.side_effect = [
        # The first time search_raw() is called it returns the result of
        # querying for the top-level annotations only.
        {
            'hits': {
                'total': 1,
                'hits': [{
                    '_id': 'parent_annotation_id',
                    '_source': 'source'
                }]
            }
        },
        # The second call returns the result of querying for all the replies to
        # those annotations
        {
            'hits': {
                'total':
                3,
                'hits': [{
                    '_id': 'reply_1',
                    '_source': 'source'
                }, {
                    '_id': 'reply_2',
                    '_source': 'source'
                }, {
                    '_id': 'reply_3',
                    '_source': 'source'
                }]
            }
        },
    ]
    # It should call Annotation() four times: first for the parent annotation
    # and then once for each reply.
    models.Annotation.side_effect = [
        mock.sentinel.parent_annotation_object,
        mock.sentinel.reply_annotation_object_1,
        mock.sentinel.reply_annotation_object_2,
        mock.sentinel.reply_annotation_object_3,
    ]

    result = core.search(mock.Mock(), mock.Mock(), separate_replies=True)

    assert result['replies'] == [
        mock.sentinel.reply_annotation_object_1,
        mock.sentinel.reply_annotation_object_2,
        mock.sentinel.reply_annotation_object_3
    ]
Example #17
0
def test_search_queries_for_replies(query):
    """It should do a second query for replies to the results of the first."""
    request = dummy_request()

    # Mock the Builder objects that Builder() returns.
    builder = mock.Mock()
    query.Builder.side_effect = [
        mock.Mock(),  # We don't care about the first Builder in this test.
        builder
    ]

    # Mock the search results.
    request.es.conn.search.side_effect = [
        # The first time search() is called it returns the result of querying
        # for the top-level annotations only.
        dummy_search_results(count=3),
        # The second call returns the result of querying for all the replies to
        # those annotations
        dummy_search_results(start=4, count=3, name='reply'),
    ]

    core.search(request, {}, separate_replies=True)

    # It should construct a RepliesMatcher for replies to the annotations from
    # the first search.
    query.RepliesMatcher.assert_called_once_with(['id_1', 'id_2', 'id_3'])

    # It should append the RepliesMatcher to the query builder.
    builder.append_matcher.assert_called_with(
        query.RepliesMatcher.return_value)

    # It should call search() a second time with the body from the
    # query builder.
    assert request.es.conn.search.call_count == 2
    _, last_call_kwargs = request.es.conn.search.call_args_list[-1]
    assert last_call_kwargs['body'] == builder.build.return_value
Example #18
0
def test_search_returns_replies(pyramid_request):
    """It should return an annotation dict for each reply from search()."""
    pyramid_request.es.conn.search.side_effect = [
        # The first time search() is called it returns the result of querying
        # for the top-level annotations only.
        dummy_search_results(count=1),
        # The second call returns the result of querying for all the replies to
        # those annotations
        dummy_search_results(start=2, count=3, name='reply'),
    ]

    result = core.search(pyramid_request, {}, separate_replies=True)

    assert result['replies'] == [
        {'name': 'reply_2', 'id': 'id_2'},
        {'name': 'reply_3', 'id': 'id_3'},
        {'name': 'reply_4', 'id': 'id_4'},
    ]
Example #19
0
def test_search_returns_replies():
    """It should return an annotation dict for each reply from search()."""
    request = dummy_request()
    request.es.conn.search.side_effect = [
        # The first time search() is called it returns the result of querying
        # for the top-level annotations only.
        dummy_search_results(count=1),
        # The second call returns the result of querying for all the replies to
        # those annotations
        dummy_search_results(start=2, count=3, name="reply"),
    ]

    result = core.search(request, {}, separate_replies=True)

    assert result["replies"] == [
        {"name": "reply_2", "id": "id_2"},
        {"name": "reply_3", "id": "id_3"},
        {"name": "reply_4", "id": "id_4"},
    ]
Example #20
0
def test_search_returns_replies(models):
    """It should return an Annotation for each reply from search_raw()."""
    models.Annotation.search_raw.side_effect = [
        # The first time search_raw() is called it returns the result of
        # querying for the top-level annotations only.
        {
            'hits': {
                'total': 1,
                'hits': [{'_id': 'parent_annotation_id', '_source': 'source'}]
            }
        },
        # The second call returns the result of querying for all the replies to
        # those annotations
        {
            'hits': {
                'total': 3,
                'hits': [
                    {'_id': 'reply_1', '_source': 'source'},
                    {'_id': 'reply_2', '_source': 'source'},
                    {'_id': 'reply_3', '_source': 'source'}
                ]
            }
        },
    ]
    # It should call Annotation() four times: first for the parent annotation
    # and then once for each reply.
    models.Annotation.side_effect = [
        mock.sentinel.parent_annotation_object,
        mock.sentinel.reply_annotation_object_1,
        mock.sentinel.reply_annotation_object_2,
        mock.sentinel.reply_annotation_object_3,
    ]

    result = core.search(mock.Mock(), mock.Mock(), separate_replies=True)

    assert result['replies'] == [
        mock.sentinel.reply_annotation_object_1,
        mock.sentinel.reply_annotation_object_2,
        mock.sentinel.reply_annotation_object_3
    ]
Example #21
0
def test_search_does_not_pass_userid_to_build(build, _):
    core.search(multidict.NestedMultiDict())
    assert build.call_args[1]["userid"] is None
Example #22
0
def test_search_does_pass_userid_to_build(build, _):
    user = mock.Mock(id="test_id")

    core.search(multidict.NestedMultiDict(), user=user)

    assert build.call_args[1]["userid"] == "test_id"
Example #23
0
def test_search_passes_private_to_AuthFilter(query):
    request = mock.Mock()

    core.search(request, mock.Mock(), private=True)

    query.AuthFilter.assert_called_once_with(request, private=True)
Example #24
0
def test_search_queries_for_replies(query, models):
    """It should do a second query for replies to the results of the first."""
    # Mock the Builder objects that Builder() returns.
    builder = mock.Mock()
    query.Builder.side_effect = [
        mock.Mock(),  # We don't care about the first Builder in this test.
        builder
    ]

    # Mock the search results that search_raw() returns.
    models.Annotation.search_raw.side_effect = [
        # The first time search_raw() is called it returns the result of
        # querying for the top-level annotations only.
        {
            'hits': {
                'total':
                3,
                'hits': [{
                    '_id': 'annotation_1',
                    '_source': 'source'
                }, {
                    '_id': 'annotation_2',
                    '_source': 'source'
                }, {
                    '_id': 'annotation_3',
                    '_source': 'source'
                }]
            }
        },
        # The second call returns the result of querying for all the replies to
        # those annotations
        {
            'hits': {
                'total':
                3,
                'hits': [{
                    '_id': 'reply_1',
                    '_source': 'source'
                }, {
                    '_id': 'reply_2',
                    '_source': 'source'
                }, {
                    '_id': 'reply_3',
                    '_source': 'source'
                }]
            }
        },
    ]

    core.search(mock.Mock(), mock.Mock(), separate_replies=True)

    # It should construct a RepliesMatcher for replies to the annotations from
    # the first search.
    query.RepliesMatcher.assert_called_once_with(
        ['annotation_1', 'annotation_2', 'annotation_3'])

    # It should append the RepliesMatcher to the query builder.
    assert builder.append_matcher.call_args_list[-1] == mock.call(
        query.RepliesMatcher.return_value)

    # It should call search_raw() a second time with the body from the
    # query builder.
    assert models.Annotation.search_raw.call_count == 2
    last_call = models.Annotation.search_raw.call_args_list[-1]
    first_arg = last_call[0][0]
    assert first_arg == builder.build.return_value
Example #25
0
def test_search_does_not_pass_userid_to_build(query):
    core.search(multidict.NestedMultiDict())
    assert query.build.call_args[1]["userid"] is None
Example #26
0
def test_search_passes_private_to_AuthFilter(query):
    request = mock.Mock()

    core.search(request, mock.Mock(), private=True)

    query.AuthFilter.assert_called_once_with(request, True)
Example #27
0
def test_search_does_pass_userid_to_build(query):
    user = mock.Mock(id="test_id")

    core.search(multidict.NestedMultiDict(), user=user)

    assert query.build.call_args[1]["userid"] == "test_id"
Example #28
0
def test_search_passes_private_to_AuthFilter(query):
    request = dummy_request()

    core.search(request, {}, private=True)

    query.AuthFilter.assert_called_once_with(request, private=True)