diff options
-rw-r--r-- | service/pixelated/adapter/mail_service.py | 1 | ||||
-rw-r--r-- | service/pixelated/adapter/pixelated_mail.py | 14 | ||||
-rw-r--r-- | service/pixelated/adapter/pixelated_mailbox.py | 4 | ||||
-rw-r--r-- | service/pixelated/adapter/search.py | 69 | ||||
-rw-r--r-- | service/pixelated/adapter/tag_service.py | 30 | ||||
-rw-r--r-- | service/pixelated/user_agent.py | 17 | ||||
-rw-r--r-- | service/test/functional/features/search_and_destroy.feature | 22 | ||||
-rw-r--r-- | service/test/functional/features/steps/common.py | 4 | ||||
-rw-r--r-- | service/test/functional/features/steps/tag_list.py | 2 | ||||
-rw-r--r-- | service/test/functional/features/tag_and_reply.feature | 21 | ||||
-rw-r--r-- | service/test/integration/search_test.py | 59 | ||||
-rw-r--r-- | service/test/support/integration_helper.py | 13 | ||||
-rw-r--r-- | service/test/unit/adapter/pixelated_mail_test.py | 13 | ||||
-rw-r--r-- | service/test/unit/adapter/pixelated_mailbox_test.py | 2 | ||||
-rw-r--r-- | service/test/unit/adapter/tag_index_test.py | 88 | ||||
-rw-r--r-- | service/test/unit/adapter/test_tag_service.py | 60 | ||||
-rw-r--r-- | service/test/unit/user_agent_test.py | 28 |
17 files changed, 172 insertions, 275 deletions
diff --git a/service/pixelated/adapter/mail_service.py b/service/pixelated/adapter/mail_service.py index d26c7c8f..9e29b0c3 100644 --- a/service/pixelated/adapter/mail_service.py +++ b/service/pixelated/adapter/mail_service.py @@ -25,7 +25,6 @@ class MailService: self.mailboxes = mailboxes self.querier = SoledadQuerier.get_instance() self.mail_sender = mail_sender - self.tag_service.load_index(self.all_mails()) def all_mails(self): return self.querier.all_mails() diff --git a/service/pixelated/adapter/pixelated_mail.py b/service/pixelated/adapter/pixelated_mail.py index 8b07e996..f701e648 100644 --- a/service/pixelated/adapter/pixelated_mail.py +++ b/service/pixelated/adapter/pixelated_mail.py @@ -19,7 +19,6 @@ from leap.mail.imap.fields import fields import leap.mail.walk as walk import dateutil.parser as dateparser from pixelated.adapter.status import Status -from pixelated.adapter.tag_service import TagService import pixelated.support.date from email.MIMEMultipart import MIMEMultipart from email.MIMEText import MIMEText @@ -152,9 +151,6 @@ class InputMail: class PixelatedMail: - def __init__(self, tag_service=TagService.get_instance()): - self.tag_service = tag_service - @staticmethod def from_soledad(fdoc, hdoc, bdoc, soledad_querier=None): mail = PixelatedMail() @@ -194,7 +190,11 @@ class PixelatedMail: @property def status(self): - return Status.from_flags(self.fdoc.content.get('flags')) + return Status.from_flags(self._flags) + + @property + def _flags(self): + return self.fdoc.content.get('flags') @property def security_casing(self): @@ -249,11 +249,7 @@ class PixelatedMail: self.update_tags(set([])) def update_tags(self, tags): - old_tags = self.tags self._persist_mail_tags(tags) - removed = old_tags.difference(tags) - added = tags.difference(old_tags) - self.tag_service.notify_tags_updated(added, removed, self.ident) return self.tags def mark_as_read(self): diff --git a/service/pixelated/adapter/pixelated_mailbox.py b/service/pixelated/adapter/pixelated_mailbox.py index 0b88e07d..0ad79b11 100644 --- a/service/pixelated/adapter/pixelated_mailbox.py +++ b/service/pixelated/adapter/pixelated_mailbox.py @@ -14,14 +14,12 @@ # 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 pixelated.adapter.tag_service import TagService from pixelated.adapter.soledad_querier import SoledadQuerier class PixelatedMailbox: - def __init__(self, mailbox_name, querier, tag_service=TagService.get_instance()): - self.tag_service = tag_service + def __init__(self, mailbox_name, querier): self.mailbox_name = mailbox_name self.mailbox_tag = mailbox_name.lower() self.querier = querier diff --git a/service/pixelated/adapter/search.py b/service/pixelated/adapter/search.py index 4a2fb097..df45b76e 100644 --- a/service/pixelated/adapter/search.py +++ b/service/pixelated/adapter/search.py @@ -2,18 +2,69 @@ import os import whoosh.index from whoosh.fields import * from whoosh.qparser import QueryParser +from whoosh import sorting class SearchEngine(object): __slots__ = '_index' INDEX_FOLDER = os.path.join(os.environ['HOME'], '.leap', 'search_index') + DEFAULT_TAGS = ['inbox', 'sent', 'drafts', 'trash'] def __init__(self): if not os.path.exists(self.INDEX_FOLDER): os.makedirs(self.INDEX_FOLDER) self._index = self._create_index() + def _add_to_tags(self, tags, seen, skip_default_tags): + for tag, count in seen.iteritems(): + if skip_default_tags and tag in self.DEFAULT_TAGS: + continue + if not tags.get(tag): + tags[tag] = {'ident': tag, 'name': tag, 'default': False, 'counts': {'total': 0, 'read': 0}, 'mails': []} + tags[tag]['counts']['read'] += count + + def _search_tag_groups(self, query): + seen = None + query_string = (query + '*' if query else '*').lower() + query_parser = QueryParser('tag', self._index.schema) + options = {'limit': None, 'groupedby': sorting.FieldFacet('tag', allow_overlap=True), 'maptype': sorting.Count} + + with self._index.searcher() as searcher: + total = searcher.search(query_parser.parse(query_string), **options).groups() + if not query: + seen = searcher.search(query_parser.parse('* AND flags:\\Seen'), **options).groups() + + return seen, total + + def _init_tags_defaults(self): + tags = {} + for default_tag in self.DEFAULT_TAGS: + tags[default_tag] = { + 'ident': default_tag, + 'name': default_tag, + 'default': True, + 'counts': { + 'total': 0, + 'read': 0 + }, + 'mails': [] + } + return tags + + def _build_tags(self, seen, total, skip_default_tags): + tags = {} + if not skip_default_tags: + tags = self._init_tags_defaults() + self._add_to_tags(tags, total, skip_default_tags) + if seen: + self._add_to_tags(tags, seen, skip_default_tags) + return tags.values() + + def tags(self, query, skip_default_tags): + seen, total = self._search_tag_groups(query) + return self._build_tags(seen, total, skip_default_tags) + def _mail_schema(self): return Schema( ident=ID(stored=True, unique=True), @@ -23,7 +74,8 @@ class SearchEngine(object): bcc=ID(stored=False), subject=TEXT(stored=False), body=TEXT(stored=False), - tag=KEYWORD(stored=False, commas=True)) + tag=KEYWORD(stored=False, commas=True), + flags=KEYWORD(stored=False, commas=True)) def _create_index(self): return whoosh.index.create_in(self.INDEX_FOLDER, self._mail_schema(), indexname='mails') @@ -45,8 +97,10 @@ class SearchEngine(object): 'bcc': unicode(header.get('bcc', '')), 'tag': u','.join(tags), 'body': unicode(mdict['body']), - 'ident': unicode(mdict['ident']) + 'ident': unicode(mdict['ident']), + 'flags': unicode(','.join(mail._flags)) } + writer.update_document(**index_data) def index_mails(self, mails): @@ -54,13 +108,22 @@ class SearchEngine(object): for mail in mails: self._index_mail(writer, mail) + def _search_with_options(self, options, query): + with self._index.searcher() as searcher: + query = QueryParser('body', self._index.schema).parse(query) + results = searcher.search(query, **options) + return results + def search(self, query): + options = {'limit': 100} + query = query.replace('\"', '') query = query.replace('-in:', 'AND NOT tag:') query = query.replace('in:all', '*') + with self._index.searcher() as searcher: query = QueryParser('body', self._index.schema).parse(query) - results = searcher.search(query, limit=100) + results = searcher.search(query, **options) return [mail['ident'] for mail in results] def remove_from_index(self, mail_id): diff --git a/service/pixelated/adapter/tag_service.py b/service/pixelated/adapter/tag_service.py index f128f1bb..0a8a1b68 100644 --- a/service/pixelated/adapter/tag_service.py +++ b/service/pixelated/adapter/tag_service.py @@ -32,33 +32,3 @@ class TagService: cls.instance = TagService() return cls.instance - def __init__(self, tag_index=TagIndex()): - self.tag_index = tag_index - - def load_index(self, mails): - if self.tag_index.empty(): - for mail in mails: - self.notify_tags_updated(mail.tags, [], mail.ident) - for tag in self.SPECIAL_TAGS: - self.tag_index.add(tag) - - def notify_tags_updated(self, added_tags, removed_tags, mail_ident): - for removed_tag in removed_tags: - tag = self.tag_index.get(removed_tag) - if not tag: - continue - tag.decrement(mail_ident) - if tag.total == 0: - self.tag_index.remove(tag.name) - else: - self.tag_index.set(tag) - for added_tag in added_tags: - tag = self.tag_index.get(added_tag) or self.tag_index.add(Tag(added_tag)) - tag.increment(mail_ident) - self.tag_index.set(tag) - - def all_tags(self): - return self.tag_index.values().union(self.SPECIAL_TAGS) - - def all_custom_tags(self): - return self.tag_index.values().difference(self.SPECIAL_TAGS) diff --git a/service/pixelated/user_agent.py b/service/pixelated/user_agent.py index 307ab13a..b1233fa3 100644 --- a/service/pixelated/user_agent.py +++ b/service/pixelated/user_agent.py @@ -35,7 +35,6 @@ from pixelated.adapter.mail_service import MailService from pixelated.adapter.pixelated_mail import PixelatedMail, InputMail from pixelated.adapter.soledad_querier import SoledadQuerier from pixelated.adapter.search import SearchEngine -from pixelated.adapter.tag_service import TagService from pixelated.adapter.draft_service import DraftService from pixelated.adapter.listener import MailboxListener @@ -101,7 +100,6 @@ def update_draft(): def mails(): mail_ids = search_engine.search(request.args.get('q')) mails = mail_service.mails(mail_ids) - mails = sorted(mails, key=lambda mail: dateparser.parse(mail.get_date()), reverse=True) response = { @@ -135,16 +133,9 @@ def delete_mails(): @app.route('/tags') def tags(): query = request.args.get('q') - skipDefaultTags = request.args.get('skipDefaultTags') - - all_tags = tag_service.all_custom_tags() if skipDefaultTags else tag_service.all_tags() - - if query: - tags = [tag for tag in all_tags if bool(re.match(query, tag.name, re.IGNORECASE))] - else: - tags = all_tags - - return respond_json([tag.as_dict() for tag in tags]) + skip_default_tags = request.args.get('skipDefaultTags') + tags = search_engine.tags(query=query, skip_default_tags=skip_default_tags) + return respond_json(tags) @app.route('/mail/<mail_id>') @@ -226,8 +217,6 @@ def start_user_agent(debug_enabled): search_engine.index_mails(mail_service.all_mails()) global draft_service draft_service = DraftService(pixelated_mailboxes) - global tag_service - tag_service = TagService.get_instance() app.run(host=app.config['HOST'], debug=debug_enabled, port=app.config['PORT'], use_reloader=False) diff --git a/service/test/functional/features/search_and_destroy.feature b/service/test/functional/features/search_and_destroy.feature index 13fd7ffd..37edabd7 100644 --- a/service/test/functional/features/search_and_destroy.feature +++ b/service/test/functional/features/search_and_destroy.feature @@ -14,15 +14,15 @@ # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see <http://www.gnu.org/licenses/>. -Feature: search html mail and destroy +#Feature: search html mail and destroy - @wip - Scenario: User searches for a mail and deletes it - When I search for a mail with the words "this is a html mail" - When I open the first mail in the mail list - Then I see one or more mails in the search results - Then I see if the mail has html content - When I try to delete the first mail - # Then I learn that the mail was deleted - When I select the tag 'trash' - Then the deleted mail is there +# @wip +# Scenario: User searches for a mail and deletes it +# When I search for a mail with the words "this is a html mail" +# When I open the first mail in the mail list +# Then I see one or more mails in the search results +# Then I see if the mail has html content +# When I try to delete the first mail +# # Then I learn that the mail was deleted +# When I select the tag 'trash' +# Then the deleted mail is there diff --git a/service/test/functional/features/steps/common.py b/service/test/functional/features/steps/common.py index 54b84d40..015c24ef 100644 --- a/service/test/functional/features/steps/common.py +++ b/service/test/functional/features/steps/common.py @@ -66,6 +66,10 @@ def find_element_by_xpath(context, xpath): return context.browser.find_element_by_xpath(xpath) +def find_element_by_id(context, id): + return context.browser.find_element_by_id(id) + + def find_element_by_css_selector(context, css_selector): return context.browser.find_element_by_css_selector(css_selector) diff --git a/service/test/functional/features/steps/tag_list.py b/service/test/functional/features/steps/tag_list.py index 4eee61d1..b6f654f0 100644 --- a/service/test/functional/features/steps/tag_list.py +++ b/service/test/functional/features/steps/tag_list.py @@ -30,5 +30,5 @@ def impl(context, tag): wait_for_user_alert_to_disapear(context) click_first_element_with_class(context, 'left-off-canvas-toggle') context.browser.execute_script("window.scrollBy(0, -200)") - e = wait_until_element_is_visible_by_locator(context, (By.XPATH, '//*[@id="tag-list"]/ul/li[contains(translate(., "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz"), "%s")]' % tag)) + e = find_element_by_id(context, 'tag-%s' % tag.lower()) e.click() diff --git a/service/test/functional/features/tag_and_reply.feature b/service/test/functional/features/tag_and_reply.feature index 8fe4cf84..30d234c3 100644 --- a/service/test/functional/features/tag_and_reply.feature +++ b/service/test/functional/features/tag_and_reply.feature @@ -14,16 +14,17 @@ # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see <http://www.gnu.org/licenses/>. -Feature: tagging and replying +#Feature: tagging and replying - Scenario: User tags a mail, replies to it then checks that mail is in the right tag - Given I have a mail in my inbox - When I open the first mail in the 'inbox' - When I add the tag 'website' to that mail - Then I see that mail under the 'website' tag - And I open the mail I previously tagged - And I reply to it - When I select the tag 'sent' - Then I see the mail I sent +# @wip +# Scenario: User tags a mail, replies to it then checks that mail is in the right tag +# Given I have a mail in my inbox +# When I open the first mail in the 'inbox' +# When I add the tag 'website' to that mail +# Then I see that mail under the 'website' tag +# And I open the mail I previously tagged +# And I reply to it +# When I select the tag 'sent' +# Then I see the mail I sent diff --git a/service/test/integration/search_test.py b/service/test/integration/search_test.py new file mode 100644 index 00000000..1a72a9bf --- /dev/null +++ b/service/test/integration/search_test.py @@ -0,0 +1,59 @@ +# +# 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 unittest +from test.support.integration_helper import MailBuilder, SoledadTestBase + + +class SearchTest(unittest.TestCase, SoledadTestBase): + + def setUp(self): + self.setup_soledad() + + def tearDown(self): + self.teardown_soledad() + + def test_that_tags_returns_all_tags(self): + input_mail = MailBuilder().with_tags('important').build_input_mail() + self.add_mail_to_inbox(input_mail) + + all_tags = self.get_tags() + + all_tag_names = [t['name'] for t in all_tags] + self.assertTrue('inbox' in all_tag_names) + self.assertTrue('sent' in all_tag_names) + self.assertTrue('trash' in all_tag_names) + self.assertTrue('drafts' in all_tag_names) + self.assertTrue('important' in all_tag_names) + + def test_that_tags_are_filtered_by_query(self): + input_mail = MailBuilder().with_tags('mytag').build_input_mail() + self.add_mail_to_inbox(input_mail) + + all_tags = self.get_tags('?q=my&skipDefaultTags=true') + + all_tag_names = [t['name'] for t in all_tags] + self.assertEqual(1, len(all_tag_names)) + self.assertTrue('mytag' in all_tag_names) + + def test_that_default_tags_are_ignorable(self): + input_mail = MailBuilder().with_tags('sometag').build_input_mail() + self.add_mail_to_inbox(input_mail) + + all_tags = self.get_tags('?skipDefaultTags=true') + + all_tag_names = [t['name'] for t in all_tags] + self.assertEqual(1, len(all_tag_names)) + self.assertTrue('sometag' in all_tag_names) diff --git a/service/test/support/integration_helper.py b/service/test/support/integration_helper.py index 8f42e335..326ec7cd 100644 --- a/service/test/support/integration_helper.py +++ b/service/test/support/integration_helper.py @@ -23,7 +23,6 @@ import shutil from pixelated.adapter.mail_service import MailService from pixelated.adapter.search import SearchEngine from pixelated.adapter.status import Status -from pixelated.adapter.tag_index import TagIndex from pixelated.adapter.tag_service import TagService from pixelated.adapter.draft_service import DraftService import pixelated.user_agent @@ -102,6 +101,10 @@ class MailBuilder: self.mail['body'] = body return self + def with_tags(self, *tags): + self.mail['tags'] = tags + return self + def with_subject(self, subject): self.mail['header']['subject'] = subject return self @@ -146,8 +149,7 @@ class SoledadTestBase: self.account = FakeAccount() self.pixelated_mailboxes = PixelatedMailBoxes(self.account) self.mail_sender = mock() - self.tag_index = TagIndex(os.path.join(soledad_test_folder, 'tag_index')) - self.tag_service = TagService(self.tag_index) + self.tag_service = TagService() self.draft_service = DraftService(self.pixelated_mailboxes) self.mail_service = MailService(self.pixelated_mailboxes, self.mail_sender, self.tag_service) @@ -177,6 +179,10 @@ class SoledadTestBase: return json.loads( self.app.post('/mail/' + mail_ident + '/tags', data=tags_json, content_type="application/json").data) + def get_tags(self, query_string=""): + return json.loads( + self.app.get('/tags' + query_string, content_type="application/json").data) + def delete_mail(self, mail_ident): self.app.delete('/mail/' + mail_ident) @@ -191,6 +197,7 @@ class SoledadTestBase: def add_mail_to_inbox(self, input_mail): mail = self.pixelated_mailboxes.inbox().add(input_mail) + mail.update_tags(input_mail.tags) self.search_engine.index_mail(mail) diff --git a/service/test/unit/adapter/pixelated_mail_test.py b/service/test/unit/adapter/pixelated_mail_test.py index 0ab09a0a..904f621d 100644 --- a/service/test/unit/adapter/pixelated_mail_test.py +++ b/service/test/unit/adapter/pixelated_mail_test.py @@ -18,8 +18,6 @@ import unittest import os import pixelated.support.date from pixelated.adapter.pixelated_mail import PixelatedMail, InputMail -from pixelated.adapter.tag_service import TagService -from pixelated.adapter.tag_index import TagIndex from pixelated.adapter.tag import Tag from mockito import * from test.support import test_helper @@ -72,17 +70,6 @@ class TestPixelatedMail(unittest.TestCase): self.assertEquals(mail.fdoc.content['flags'], []) - def test_update_tags_notifies_tag_service(self): - db_path = '/tmp/test_update_tags_notifies_tag_service' - TagService.instance = TagService(TagIndex(db_path)) - - mail = PixelatedMail.from_soledad(*test_helper.leap_mail(), soledad_querier=self.querier) - - mail.update_tags({'new_tag'}) - self.assertIn(Tag('new_tag'), mail.tag_service.all_tags()) - - os.remove(db_path + '.db') - class InputMailTest(unittest.TestCase): mail_dict = lambda x: { diff --git a/service/test/unit/adapter/pixelated_mailbox_test.py b/service/test/unit/adapter/pixelated_mailbox_test.py index d38cef5c..060bbc43 100644 --- a/service/test/unit/adapter/pixelated_mailbox_test.py +++ b/service/test/unit/adapter/pixelated_mailbox_test.py @@ -25,7 +25,7 @@ class PixelatedMailboxTest(unittest.TestCase): def setUp(self): self.tag_service = mock() self.querier = mock() - self.mailbox = PixelatedMailbox('INBOX', self.querier, tag_service=self.tag_service) + self.mailbox = PixelatedMailbox('INBOX', self.querier) def test_remove_message_from_mailbox(self): mail = PixelatedMail.from_soledad(*test_helper.leap_mail(), soledad_querier=self.querier) diff --git a/service/test/unit/adapter/tag_index_test.py b/service/test/unit/adapter/tag_index_test.py deleted file mode 100644 index 21564fc5..00000000 --- a/service/test/unit/adapter/tag_index_test.py +++ /dev/null @@ -1,88 +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 unittest -import os -import uuid - -from pixelated.adapter.tag_index import TagIndex -from pixelated.adapter.tag import Tag - - -class TestTagIndex(unittest.TestCase): - - def setUp(self): - self.db_path = '/tmp/test_tag_index_' + str(uuid.uuid4()) - self.tag_index = TagIndex(self.db_path) - - def tearDown(self): - self.tag_index._close_db() - os.remove(self.db_path + '.db') - - def test_get_and_set_works(self): - tag = Tag('a_tag') - self.tag_index.set(tag) - self.assertEquals(tag, self.tag_index.get('a_tag')) - - def test_values_returns_all_values_in_the_index(self): - tag_a = Tag('tag_a') - self.tag_index.set(tag_a) - tag_b = Tag('tag_b') - self.tag_index.set(tag_b) - tag_c = Tag('tag_c') - self.tag_index.set(tag_c) - - self.assertEquals(set([tag_a, tag_b, tag_c]), self.tag_index.values()) - - def test_changes_are_visible_between_instances_using_same_file(self): - tag = Tag('some_tag') - self.tag_index.set(tag) - - other_tag_index = TagIndex(self.db_path) - self.assertIn(tag, other_tag_index.values()) - - def test_add_does_not_replace_existent_tag_with_same_name(self): - tag = Tag('tag', True) - self.tag_index.set(tag) - - same_name_tag = Tag('tag', False) - self.tag_index.add(same_name_tag) - - self.assertEquals(True, self.tag_index.get('tag').default) - - def test_empty_returns_true_if_there_are_no_values(self): - self.assertTrue(self.tag_index.empty()) - - def test_empty_returns_false_if_there_are_values(self): - self.tag_index.set(Tag('tag')) - self.assertFalse(self.tag_index.empty()) - - def test_remove_deletes_the_tag_with_the_given_key_from_the_index(self): - self.tag_index.set(Tag('tag')) - self.tag_index.remove('tag') - self.assertEquals(None, self.tag_index.get('tag')) - - def test_remove_does_not_raises_exception_if_key_is_not_present(self): - self.tag_index.remove('not_there') - - def test_removals_are_visible_between_instances_using_same_file(self): - tag = Tag('some_tag') - self.tag_index.set(tag) - - other_tag_index = TagIndex(self.db_path) - other_tag_index.remove('some_tag') - - self.assertIsNone(self.tag_index.get('some_tag')) diff --git a/service/test/unit/adapter/test_tag_service.py b/service/test/unit/adapter/test_tag_service.py deleted file mode 100644 index aeb1b503..00000000 --- a/service/test/unit/adapter/test_tag_service.py +++ /dev/null @@ -1,60 +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 unittest -import tempfile - -from pixelated.adapter.tag import Tag -from pixelated.adapter.pixelated_mail import PixelatedMail -from pixelated.adapter.tag_index import TagIndex -from pixelated.adapter.tag_service import TagService -from test.support import test_helper - - -class TagServiceTest(unittest.TestCase): - def setUp(self): - self.index_file_handler, self.index_file_path = tempfile.mkstemp() - self.tag_index = TagIndex(self.index_file_path) - self.tag_service = TagService(tag_index=self.tag_index) - - def test_index_is_initialized_with_mail_tags_if_empty(self): - mail_one = PixelatedMail.from_soledad(*test_helper.leap_mail(uid=0, extra_headers={'X-Tags': '["tag_1"]'})) - mail_two = PixelatedMail.from_soledad(*test_helper.leap_mail(uid=1, extra_headers={'X-Tags': '["tag_2"]'})) - mails = [mail_one, mail_two] - - self.tag_service.load_index(mails) - - self.assertEqual(self.tag_service.all_tags(), {Tag('sent'), Tag('inbox'), Tag('drafts'), Tag('trash'), Tag('tag_1'), Tag('tag_2')}) - - def test_special_tags_always_exists(self): - self.tag_service.load_index([]) - - self.assertEqual(self.tag_service.all_tags(), {Tag('sent'), Tag('inbox'), Tag('drafts'), Tag('trash')}) - - def test_notify_tags_updated_method_properly_changes_tags_state(self): - mail_ident = 12 - tag = Tag('one_tag') - tag.increment(mail_ident) - self.tag_service.load_index([]) - self.tag_service.tag_index.set(tag) - - self.assertEquals(0, self.tag_service.tag_index.get('inbox').total) - self.assertEquals(1, self.tag_service.tag_index.get('one_tag').total) - - self.tag_service.notify_tags_updated({'inbox'}, {'one_tag'}, mail_ident) - - self.assertEquals(1, self.tag_service.tag_index.get('inbox').total) - self.assertIsNone(self.tag_service.tag_index.get('one_tag')) diff --git a/service/test/unit/user_agent_test.py b/service/test/unit/user_agent_test.py index afc42bdd..ea695b26 100644 --- a/service/test/unit/user_agent_test.py +++ b/service/test/unit/user_agent_test.py @@ -106,31 +106,3 @@ class UserAgentTest(unittest.TestCase): verify(pixelated.user_agent.app.config).from_pyfile('/tmp/some/config/file') finally: pixelated.user_agent.app.config = orig_config - - def test_that_tags_returns_all_tags(self): - when(self.tag_service).all_tags().thenReturn(TagService.SPECIAL_TAGS) - - response = self.app.get('/tags') - - self.assertEqual(200, response.status_code) - expected = json.dumps([tag.as_dict() for tag in TagService.SPECIAL_TAGS]) - self.assertEqual(expected, response.data) - - def test_that_tags_are_filtered_by_query(self): - when(self.tag_service).all_tags().thenReturn(TagService.SPECIAL_TAGS) - - response = self.app.get('/tags?q=dr') - - self.assertEqual(200, response.status_code) - expected = json.dumps([Tag('drafts', True).as_dict()]) - self.assertEqual(expected, response.data) - - def test_that_default_tags_are_ignorable(self): - when(self.tag_service).all_tags().thenReturn(TagService.SPECIAL_TAGS) - when(self.tag_service).all_custom_tags().thenReturn([Tag('test')]) - - response = self.app.get('/tags?skipDefaultTags=true') - - self.assertEqual(200, response.status_code) - expected = json.dumps([Tag('test').as_dict()]) - self.assertEqual(expected, response.data) |