← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~wgrant/launchpad/question-search-api into lp:launchpad

 

William Grant has proposed merging lp:~wgrant/launchpad/question-search-api into lp:launchpad.

Commit message:
Export QuestionSet.searchQuestions on the webservice.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~wgrant/launchpad/question-search-api/+merge/253009

Export QuestionSet.searchQuestions on the webservice. Question targets' methods were already exported.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wgrant/launchpad/question-search-api into lp:launchpad.
=== modified file 'lib/lp/answers/interfaces/questioncollection.py'
--- lib/lp/answers/interfaces/questioncollection.py	2013-01-07 02:40:55 +0000
+++ lib/lp/answers/interfaces/questioncollection.py	2015-03-15 23:49:41 +0000
@@ -46,8 +46,23 @@
     """An object that can be used to search through a collection of questions.
     """
 
+    @operation_parameters(
+        search_text=TextLine(
+            title=_('Search text'), required=False),
+        status=List(
+            title=_('Status'), required=False,
+            value_type=Choice(vocabulary=QuestionStatus)),
+        language=List(
+            title=_('Language'), required=False,
+            value_type=ReferenceChoice(vocabulary='Language')),
+        sort=Choice(
+            title=_('Sort'), required=False,
+            vocabulary=QuestionSort))
+    @operation_returns_collection_of(Interface)  # IQuestion.
+    @export_read_operation()
+    @operation_for_version('devel')
     def searchQuestions(search_text=None,
-                        status=QUESTION_STATUS_DEFAULT_SEARCH,
+                        status=list(QUESTION_STATUS_DEFAULT_SEARCH),
                         language=None, sort=None):
         """Return the questions from the collection matching search criteria.
 

=== modified file 'lib/lp/answers/interfaces/webservice.py'
--- lib/lp/answers/interfaces/webservice.py	2012-01-01 02:58:52 +0000
+++ lib/lp/answers/interfaces/webservice.py	2015-03-15 23:49:41 +0000
@@ -19,6 +19,7 @@
 
 from lp.answers.interfaces.question import IQuestion
 from lp.answers.interfaces.questioncollection import (
+    IQuestionCollection,
     IQuestionSet,
     ISearchableByQuestionOwner,
     )
@@ -39,6 +40,8 @@
 patch_collection_return_type(
     IQuestionTarget, 'findSimilarQuestions', IQuestion)
 patch_collection_return_type(
+    IQuestionCollection, 'searchQuestions', IQuestion)
+patch_collection_return_type(
     ISearchableByQuestionOwner, 'searchQuestions', IQuestion)
 patch_reference_property(IQuestionMessage, 'question', IQuestion)
 patch_reference_property(IQuestionSubscription, 'question', IQuestion)

=== modified file 'lib/lp/answers/tests/test_question_webservice.py'
--- lib/lp/answers/tests/test_question_webservice.py	2012-10-30 16:59:58 +0000
+++ lib/lp/answers/tests/test_question_webservice.py	2015-03-15 23:49:41 +0000
@@ -8,6 +8,7 @@
 from BeautifulSoup import BeautifulSoup
 from lazr.restfulclient.errors import HTTPError
 from simplejson import dumps
+from testtools.matchers import Equals
 import transaction
 from zope.security.proxy import removeSecurityProxy
 
@@ -21,10 +22,12 @@
     QuestionTargetError,
     )
 from lp.testing import (
+    admin_logged_in,
     celebrity_logged_in,
     launchpadlib_for,
     logout,
     person_logged_in,
+    record_two_runs,
     TestCase,
     TestCaseWithFactory,
     ws_object,
@@ -34,7 +37,11 @@
     DatabaseFunctionalLayer,
     FunctionalLayer,
     )
-from lp.testing.pages import LaunchpadWebServiceCaller
+from lp.testing.matchers import HasQueryCount
+from lp.testing.pages import (
+    LaunchpadWebServiceCaller,
+    webservice_for_person,
+    )
 from lp.testing.views import create_webservice_error_view
 
 
@@ -243,3 +250,37 @@
 
         # Check the results.
         self.assertFalse(db_question.isSubscribed(db_person))
+
+
+class TestQuestionSetWebService(TestCaseWithFactory):
+
+    layer = DatabaseFunctionalLayer
+
+    def test_searchQuestions(self):
+        created = [self.factory.makeQuestion(title="foo") for i in range(10)]
+        webservice = webservice_for_person(self.factory.makePerson())
+        collection = webservice.named_get(
+            '/questions', 'searchQuestions', search_text='foo',
+            sort='oldest first', api_version='devel').jsonBody()
+        # The first few matching questions are returned.
+        self.assertEqual(
+            [q.id for q in created[:5]],
+            [int(q['self_link'].rsplit('/', 1)[-1])
+             for q in collection['entries']])
+
+    def test_searchQuestions_query_count(self):
+        webservice = webservice_for_person(self.factory.makePerson())
+
+        def create_question():
+            with admin_logged_in():
+                self.factory.makeQuestion(title="foobar")
+
+        def search_questions():
+            webservice.named_get(
+                '/questions', 'searchQuestions', search_text='foobar',
+                api_version='devel').jsonBody()
+
+        search_questions()
+        recorder1, recorder2 = record_two_runs(
+            search_questions, create_question, 2)
+        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))


Follow ups