<commit_before># test_filtering.py - unit tests for filtering resources in client requests
#
# Copyright 2011 <NAME> <<EMAIL>>.
# Copyright 2012, 2013, 2014, 2015, 2016 <NAME>
#           <<EMAIL>> and contributors.
#
# This file is part of Flask-Restless.
#
# Flask-Restless is distributed under both the GNU Affero General Public
# License version 3 and under the 3-clause BSD license. For more
# information, see LICENSE.AGPL and LICENSE.BSD.
"""Unit tests for filtering resources in client requests."""
from datetime import date
from datetime import datetime
from datetime import time
from operator import itemgetter

from sqlalchemy import Column
from sqlalchemy import Date
from sqlalchemy import DateTime
from sqlalchemy import ForeignKey
from sqlalchemy import Integer
from sqlalchemy import Time
from sqlalchemy import Unicode
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.orm import backref
from sqlalchemy.orm import relationship

from .helpers import check_sole_error
from .helpers import dumps
from .helpers import loads
from .helpers import skip
from .helpers import ManagerTestBase


class SearchTestBase(ManagerTestBase):
    """Provides a search method that simplifies a fetch request with filtering
    query parameters.

    """

    def search(self, url, filters=None, single=None):
        """Convenience function for performing a filtered :http:method:`get`
        request.

        `url` is the ``path`` part of the URL to which the request will be
        sent.

        If `filters` is specified, it must be a Python list containing filter
        objects. It specifies how to set the ``filter[objects]`` query
        parameter.

        If `single` is specified, it must be a Boolean. It specifies how to set
        the ``filter[single]`` query parameter.

        """
        if filters is None:
            filters = []
        params = {'filter[objects]': dumps(filters)}
        if single is not None:
            params['filter[single]'] = 1 if single else 0
        return self.app.get(url, query_string=params)


class TestFiltering(SearchTestBase):
    """Tests for filtering resources.

    For more information, see the `Filtering`_ section of the JSON API
    specification.

    .. _Filtering: http://jsonapi.org/format/#fetching-filtering

    """

    def setup(self):
        """Creates the database, the :class:`~flask.Flask` object, the
        :class:`~flask.ext.restless.manager.APIManager` for that application,
        and creates the ReSTful API endpoints for the models used in the test
        methods.

        """
        super(TestFiltering, self).setup()

        class Article(self.Base):
            __tablename__ = 'article'
            id = Column(Integer, primary_key=True)
            author_id = Column(Integer, ForeignKey('person.id'))
            author = relationship('Person', backref=backref('articles'))

        class Person(self.Base):
            __tablename__ = 'person'
            id = Column(Integer, primary_key=True)
            name = Column(Unicode)
            age = Column(Integer)
            birthday = Column(Date)
            birth_datetime = Column(DateTime)
            bedtime = Column(Time)

        class Comment(self.Base):
            __tablename__ = 'comment'
            id = Column(Integer, primary_key=True)
            content = Column(Unicode)
            article_id = Column(Integer, ForeignKey('article.id'))
            article = relationship(Article, backref=backref('comments'))
            author_id = Column(Integer, ForeignKey('person.id'))
            author = relationship(Person, backref=backref('comments'))

        self.Article = Article
        self.Person = Person
        self.Comment = Comment
        self.Base.metadata.create_all()
        self.manager.create_api(Article)
        self.manager.create_api(Person)
        # HACK Need to create APIs for these other models because otherwise
        # we're not able to create the link URLs to them.
        #
        # TODO Fix this by simply not creating links to related models for
        # which no API has been made.
        self.manager.create_api(Comment)

    def test_bad_filter(self):
        """Tests that providing a bad filter parameter causes an error
        response.

        """
        query_string = {'filter[objects]': 'bogus'}
        response = self.app.get('/api/person', query_string=query_string)
        assert response.status_code == 400
        # TODO check error messages here

    def test_bad_filter_relationship(self):
        """Test for providing a bad filter parameter for fetching
        relationship objects.

        """<commit_msg>Adds test for bad filter when fetching a relation<commit_after># test_filtering.py - unit tests for filtering resources in client requests
#
# Copyright 2011 <NAME> <<EMAIL>>.
# Copyright 2012, 2013, 2014, 2015, 2016 <NAME>
#           <<EMAIL>> and contributors.
#
# This file is part of Flask-Restless.
#
# Flask-Restless is distributed under both the GNU Affero General Public
# License version 3 and under the 3-clause BSD license. For more
# information, see LICENSE.AGPL and LICENSE.BSD.
"""Unit tests for filtering resources in client requests."""
from datetime import date
from datetime import datetime
from datetime import time
from operator import itemgetter

from sqlalchemy import Column
from sqlalchemy import Date
from sqlalchemy import DateTime
from sqlalchemy import ForeignKey
from sqlalchemy import Integer
from sqlalchemy import Time
from sqlalchemy import Unicode
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.orm import backref
from sqlalchemy.orm import relationship

from .helpers import check_sole_error
from .helpers import dumps
from .helpers import loads
from .helpers import skip
from .helpers import ManagerTestBase


class SearchTestBase(ManagerTestBase):
    """Provides a search method that simplifies a fetch request with filtering
    query parameters.

    """

    def search(self, url, filters=None, single=None):
        """Convenience function for performing a filtered :http:method:`get`
        request.

        `url` is the ``path`` part of the URL to which the request will be
        sent.

        If `filters` is specified, it must be a Python list containing filter
        objects. It specifies how to set the ``filter[objects]`` query
        parameter.

        If `single` is specified, it must be a Boolean. It specifies how to set
        the ``filter[single]`` query parameter.

        """
        if filters is None:
            filters = []
        params = {'filter[objects]': dumps(filters)}
        if single is not None:
            params['filter[single]'] = 1 if single else 0
        return self.app.get(url, query_string=params)


class TestFiltering(SearchTestBase):
    """Tests for filtering resources.

    For more information, see the `Filtering`_ section of the JSON API
    specification.

    .. _Filtering: http://jsonapi.org/format/#fetching-filtering

    """

    def setup(self):
        """Creates the database, the :class:`~flask.Flask` object, the
        :class:`~flask.ext.restless.manager.APIManager` for that application,
        and creates the ReSTful API endpoints for the models used in the test
        methods.

        """
        super(TestFiltering, self).setup()

        class Article(self.Base):
            __tablename__ = 'article'
            id = Column(Integer, primary_key=True)
            author_id = Column(Integer, ForeignKey('person.id'))
            author = relationship('Person', backref=backref('articles'))

        class Person(self.Base):
            __tablename__ = 'person'
            id = Column(Integer, primary_key=True)
            name = Column(Unicode)
            age = Column(Integer)
            birthday = Column(Date)
            birth_datetime = Column(DateTime)
            bedtime = Column(Time)

        class Comment(self.Base):
            __tablename__ = 'comment'
            id = Column(Integer, primary_key=True)
            content = Column(Unicode)
            article_id = Column(Integer, ForeignKey('article.id'))
            article = relationship(Article, backref=backref('comments'))
            author_id = Column(Integer, ForeignKey('person.id'))
            author = relationship(Person, backref=backref('comments'))

        self.Article = Article
        self.Person = Person
        self.Comment = Comment
        self.Base.metadata.create_all()
        self.manager.create_api(Article)
        self.manager.create_api(Person)
        # HACK Need to create APIs for these other models because otherwise
        # we're not able to create the link URLs to them.
        #
        # TODO Fix this by simply not creating links to related models for
        # which no API has been made.
        self.manager.create_api(Comment)

    def test_bad_filter(self):
        """Tests that providing a bad filter parameter causes an error
        response.

        """
        query_string = {'filter[objects]': 'bogus'}
        response = self.app.get('/api/person', query_string=query_string)
        assert response.status_code == 400
        # TODO check error messages here

    def test_bad_filter_relation(self):
        """Tests for providing a bad filter parameter for fetching a
        relation.

        """
        query_string = {'filter[objects]': 'bogus'}
        response = self.app.get('/api/person/1/articles',
                                query_string=query_string)
        check_sole_error(response, 400, ['Unable to decode', 'filter object'])

    def test_bad_filter_relationship(self):
        """Test for providing a bad filter parameter for fetching
        relationship objects.

        """
{'fraction_non_alphanumeric': 0.08455317842153752, 'fraction_numerical': 0.006756065103900092, 'mean_word_length': 2.7332823844096295, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6852599', 'n_tokens_mistral': 2631, 'n_tokens_neox': 2485, 'n_words': 902}