diff options
| -rw-r--r-- | service/pixelated/resources/__init__.py | 3 | ||||
| -rw-r--r-- | service/pixelated/resources/mails_resource.py | 8 | ||||
| -rw-r--r-- | service/test/integration/retrieve_attachment_test.py | 8 | ||||
| -rw-r--r-- | service/test/support/integration/app_test_client.py | 43 | ||||
| -rw-r--r-- | service/test/support/test_helper.py | 21 | ||||
| -rw-r--r-- | service/test/unit/controllers/mails_controller_test.py | 126 | ||||
| -rw-r--r-- | service/test/unit/resources/__init__.py (renamed from service/test/unit/controllers/__init__.py) | 0 | ||||
| -rw-r--r-- | service/test/unit/resources/sync_info_controller_test.py (renamed from service/test/unit/controllers/sync_info_controller_test.py) | 11 | 
8 files changed, 58 insertions, 162 deletions
diff --git a/service/pixelated/resources/__init__.py b/service/pixelated/resources/__init__.py index a2e4c9d4..9e9c154e 100644 --- a/service/pixelated/resources/__init__.py +++ b/service/pixelated/resources/__init__.py @@ -19,7 +19,8 @@ def respond_json(entity, request, status_code=200):      json_response = json.dumps(entity)      request.responseHeaders.addRawHeader(b"content-type", b"application/json")      request.code = status_code -    return json_response +    request.write(json_response) +    request.finish()  def respond_json_deferred(entity, request, status_code=200): diff --git a/service/pixelated/resources/mails_resource.py b/service/pixelated/resources/mails_resource.py index 75c73349..d391382d 100644 --- a/service/pixelated/resources/mails_resource.py +++ b/service/pixelated/resources/mails_resource.py @@ -24,7 +24,7 @@ class MailsUnreadResource(Resource):          for ident in idents:              mail = self._mail_service.mark_as_unread(ident)              self._search_engine.index_mail(mail) -        return "" +        return respond_json(None, request)  class MailsReadResource(Resource): @@ -42,7 +42,7 @@ class MailsReadResource(Resource):          for ident in idents:              mail = self._mail_service.mark_as_read(ident)              self._search_engine.index_mail(mail) -        return "" +        return respond_json(None, request)  class MailsDeleteResource(Resource): @@ -89,11 +89,11 @@ class MailsResource(Resource):          response = {              "stats": {                  "total": total, -                }, +            },              "mails": [mail.as_dict() for mail in mails]          } -        return json.dumps(response) +        return respond_json(response, request)      def render_POST(self, request):          try: diff --git a/service/test/integration/retrieve_attachment_test.py b/service/test/integration/retrieve_attachment_test.py index 5f754a27..41ffd89d 100644 --- a/service/test/integration/retrieve_attachment_test.py +++ b/service/test/integration/retrieve_attachment_test.py @@ -36,6 +36,10 @@ class RetrieveAttachmentTest(SoledadTestBase):          self.client.add_document_to_soledad(attachment_dict) -        attachment = self.get_attachment(ident, 'base64') +        d = self.get_attachment(ident, 'base64') -        self.assertEquals('pequeno anexo :D\n', attachment) +        def _assert(attachment): +            self.assertEquals('pequeno anexo :D\n', attachment) +        d.addCallback(_assert) +         +        return d diff --git a/service/test/support/integration/app_test_client.py b/service/test/support/integration/app_test_client.py index b032eefd..47674e75 100644 --- a/service/test/support/integration/app_test_client.py +++ b/service/test/support/integration/app_test_client.py @@ -18,8 +18,6 @@ import multiprocessing  import shutil  import time -from pixelated.config.routes import setup_routes -from klein.test_resource import requestMock, _render  from leap.mail.imap.account import SoledadBackedAccount  from leap.soledad.client import Soledad  from mock import MagicMock, Mock @@ -29,12 +27,15 @@ from pixelated.adapter.services.mail_service import MailService  from pixelated.adapter.services.mailboxes import Mailboxes  from pixelated.adapter.soledad.soledad_querier import SoledadQuerier  from pixelated.adapter.services.tag_service import TagService -from pixelated.resources import FeaturesController, HomeController, MailsController, TagsController, \ -    SyncInfoController, AttachmentsController, ContactsController +from pixelated.resources.root_resource import RootResource  import pixelated.runserver  from pixelated.adapter.model.mail import PixelatedMail  from pixelated.adapter.search import SearchEngine  from test.support.integration.model import MailBuilder +from test.support.test_helper import request_mock +from twisted.internet.defer import succeed +from twisted.web import server +from twisted.web.resource import getChildForRequest  class AppTestClient: @@ -63,32 +64,26 @@ class AppTestClient:          self.search_engine = SearchEngine(self.soledad_querier)          self.search_engine.index_mails(self.mail_service.all_mails()) -        features_controller = FeaturesController() -        features_controller.DISABLED_FEATURES.append('autoReload') -        home_controller = HomeController() -        mails_controller = MailsController(mail_service=self.mail_service, -                                           draft_service=self.draft_service, -                                           search_engine=self.search_engine) -        tags_controller = TagsController(search_engine=self.search_engine) -        contacts_controller = ContactsController(search_engine=self.search_engine) -        sync_info_controller = SyncInfoController() -        attachments_controller = AttachmentsController(self.soledad_querier) +        self.app.resource = RootResource() -        setup_routes(self.app, home_controller, mails_controller, tags_controller, -                     features_controller, sync_info_controller, attachments_controller, contacts_controller) +        self.app.resource.initialize(self.soledad_querier, self.search_engine, self.mail_service, self.draft_service)      def _render(self, request, as_json=True):          def get_request_written_data(_=None): -            written_data = request.getWrittenData() +            written_data = None +            if len(request.written): +                written_data = request.written[0]              if written_data:                  return json.loads(written_data) if as_json else written_data -        d = _render(self.app.resource(), request) +        resource = getChildForRequest(self.app.resource, request) + +        result = resource.render(request) +          if request.finished:              return get_request_written_data(), request          else: -            d.addCallback(get_request_written_data) -            return d, request +            return request.notifyFinish().addCallback(lambda _: request).addCallback(get_request_written_data), request      def run_on_a_thread(self, logfile='/tmp/app_test_client.log', port=4567, host='localhost'):          worker = lambda: self.app.run(host=host, port=port, logFile=open(logfile, 'w')) @@ -98,20 +93,20 @@ class AppTestClient:          return lambda: process.terminate()      def get(self, path, get_args, as_json=True): -        request = requestMock(path) +        request = request_mock(path)          request.args = get_args          return self._render(request, as_json)      def post(self, path, body=''): -        request = requestMock(path=path, method="POST", body=body, headers={'Content-Type': ['application/json']}) +        request = request_mock(path=path, method="POST", body=body, headers={'Content-Type': ['application/json']})          return self._render(request)      def put(self, path, body): -        request = requestMock(path=path, method="PUT", body=body, headers={'Content-Type': ['application/json']}) +        request = request_mock(path=path, method="PUT", body=body, headers={'Content-Type': ['application/json']})          return self._render(request)      def delete(self, path, body=""): -        request = requestMock(path=path, body=body, headers={'Content-Type': ['application/json']}, method="DELETE") +        request = request_mock(path=path, body=body, headers={'Content-Type': ['application/json']}, method="DELETE")          return self._render(request)      def add_document_to_soledad(self, _dict): diff --git a/service/test/support/test_helper.py b/service/test/support/test_helper.py index ff1de64a..f43776d1 100644 --- a/service/test/support/test_helper.py +++ b/service/test/support/test_helper.py @@ -14,6 +14,7 @@  # You should have received a copy of the GNU Affero General Public License  # along with Pixelated. If not, see <http://www.gnu.org/licenses/>.  from datetime import datetime +import io  from pixelated.adapter.model.mail import InputMail @@ -79,3 +80,23 @@ class TestRequest:      def __init__(self, json):          self.json = json + + +from twisted.web.test.test_web import DummyRequest + + +class PixRequestMock(DummyRequest): +    def __init__(self, path): +        DummyRequest.__init__(self, path) +        self.content = None +        self.code = None + + +def request_mock(path='', method='GET', body='', headers={}): +    dummy = PixRequestMock(path.split('/')) +    for name, value in headers.iteritems(): +        dummy.setHeader(name, value) +    dummy.method = method +    dummy.content = io.BytesIO(body) +    return dummy + diff --git a/service/test/unit/controllers/mails_controller_test.py b/service/test/unit/controllers/mails_controller_test.py deleted file mode 100644 index 7e5d0e7d..00000000 --- a/service/test/unit/controllers/mails_controller_test.py +++ /dev/null @@ -1,126 +0,0 @@ -# -# Copyright (c) 2014 ThoughtWorks, Inc. -# -# Pixelated is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pixelated is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Pixelated. If not, see <http://www.gnu.org/licenses/>. -import json -import unittest -from io import BytesIO - -from klein.test_resource import requestMock -from mock import MagicMock -from mockito import * -from pixelated.resources.mails_controller import MailsController - - -class TestMailsController(unittest.TestCase): - -    def setUp(self): -        self.mail_service = mock() -        self.search_engine = mock() -        self.dummy_request = MagicMock(spec=['code', 'responseHeaders']) -        draft_service = mock() - -        self.mails_controller = MailsController(mail_service=self.mail_service, -                                                draft_service=draft_service, -                                                search_engine=self.search_engine) - -        self.input_mail = mock() -        self.input_mail.json = {'header': {'from': 'a@a.a', 'to': 'b@b.b'}, -                                'ident': 1, -                                'tags': [], -                                'status': [], -                                'security_casing': {}, -                                'body': 'email body'} - -    def tearDown(self): -        unstub() - -    def test_sending_mail_return_sent_mail_data_when_send_succeeds(self): -        self.mail_service.send = self._successfuly_send_mail -        request = requestMock('', body=json.dumps(self.input_mail.json)) - -        result = self.mails_controller.send_mail(request) - -        self.assertEqual(request.code, 200) -        self.assertEqual(result, -                         '{"status": [], "body": "email body", "ident": 1, "tags": [], "header": {"to": "b@b.b", "from": "a@a.a"}, "security_casing": {}}') - -    def test_sending_mail_return_error_message_when_send_fails(self): -        self.mail_service.send = self._send_that_throws_exception - -        request = requestMock('', body=json.dumps(self.input_mail.json)) -        result = self.mails_controller.send_mail(request) - -        self.assertEqual(request.code, 422) -        self.assertEqual(result, -                         '{"message": "email sending failed\\nmore information of error\\n123\\nthere was a code before this"}') - -    def test_fetching_mail_gets_mail_from_mail_service(self): -        mail = mock() -        mail.as_dict = lambda: {'ident': 1, 'body': 'le mail body'} -        when(self.mail_service).mail(1).thenReturn(mail) - -        response = self.mails_controller.mail(self.dummy_request, 1) - -        verify(self.mail_service).mail(1) -        self.assertEqual(response, '{"body": "le mail body", "ident": 1}') - -    def test_marking_mail_as_read_set_mail_as_read_on_the_service(self): -        mail = mock() -        when(self.mail_service).mark_as_read("1").thenReturn(mail) -        when(self.search_engine).index_mail(mail).thenReturn(None) -        self.dummy_request.content = BytesIO('{"idents":["1"]}') - -        self.mails_controller.mark_many_mail_read(self.dummy_request) - -        verify(self.mail_service).mark_as_read(u'1') -        verify(self.search_engine).index_mail(mail) - -    def test_marking_mail_as_unread_set_mail_as_unread_on_the_service(self): -        mail = mock() -        when(self.mail_service).mark_as_unread("1").thenReturn(mail) -        when(self.search_engine).index_mail(mail).thenReturn(None) -        self.dummy_request.content = BytesIO('{"idents":["1"]}') - -        self.mails_controller.mark_many_mail_unread(self.dummy_request) - -        verify(self.mail_service).mark_as_unread(u'1') -        verify(self.search_engine).index_mail(mail) - -    def test_move_message_to_trash(self): -        mail = mock() -        mail.mailbox_name = 'INBOX' -        when(self.mail_service).mail(1).thenReturn(mail) -        when(self.mail_service).delete_mail(1).thenReturn(mail) - -        self.mails_controller.delete_mail(self.dummy_request, 1) - -        verify(self.search_engine).index_mail(mail) - -    def test_delete_permanently_when_mail_in_trash(self): -        mail = mock() -        mail.mailbox_name = 'TRASH' -        when(self.mail_service).mail(1).thenReturn(mail) -        self.mails_controller.delete_mail(self.dummy_request, 1) - -        verify(self.mail_service).delete_permanent(1) - -    def _successfuly_send_mail(self, ident, mail): -        sent_mail = mock() -        sent_mail.as_dict = lambda: self.input_mail.json - -        return sent_mail - -    def _send_that_throws_exception(self, ident, mail): -        raise Exception('email sending failed', 'more information of error', 123, 'there was a code before this') diff --git a/service/test/unit/controllers/__init__.py b/service/test/unit/resources/__init__.py index e69de29b..e69de29b 100644 --- a/service/test/unit/controllers/__init__.py +++ b/service/test/unit/resources/__init__.py diff --git a/service/test/unit/controllers/sync_info_controller_test.py b/service/test/unit/resources/sync_info_controller_test.py index 1fb38822..c24c7181 100644 --- a/service/test/unit/controllers/sync_info_controller_test.py +++ b/service/test/unit/resources/sync_info_controller_test.py @@ -16,16 +16,16 @@  import unittest  import json -from mock import MagicMock -from pixelated.resources import SyncInfoController +from test.support.test_helper import request_mock +from pixelated.resources.sync_info_resource import SyncInfoResource  from mockito import *  class SyncInfoControllerTest(unittest.TestCase):      def setUp(self): -        self.dummy_request = MagicMock() -        self.controller = SyncInfoController() +        self.dummy_request = request_mock() +        self.controller = SyncInfoResource()      def _set_count(self, current, total):          soledad_sync_data = mock() @@ -33,7 +33,8 @@ class SyncInfoControllerTest(unittest.TestCase):          self.controller.set_sync_info(soledad_sync_data)      def get_sync_info(self): -        return json.loads(self.controller.sync_info(self.dummy_request)) +        self.controller.render_GET(self.dummy_request) +        return json.loads(self.dummy_request.written[0])      def test_is_not_syncing_if_total_is_equal_to_current(self):          self._set_count(total=0, current=0)  | 
