Example #1
0
def test_thread_count(db, api_client, default_account):
    date1 = datetime.datetime(2015, 1, 1, 0, 0, 0)
    date2 = datetime.datetime(2012, 1, 1, 0, 0, 0)
    date3 = datetime.datetime(2010, 1, 1, 0, 0, 0)
    date4 = datetime.datetime(2009, 1, 1, 0, 0, 0)
    date5 = datetime.datetime(2008, 1, 1, 0, 0, 0)

    thread1 = add_fake_thread(db.session, default_account.namespace.id)
    thread2 = add_fake_thread(db.session, default_account.namespace.id)

    test_subject = "test_thread_view_count_with_category"

    for thread in [thread1, thread2]:
        add_fake_message(db.session, default_account.namespace.id, thread,
                         subject=test_subject, received_date=date1)
        add_fake_message(db.session, default_account.namespace.id, thread,
                         subject=test_subject, received_date=date2,
                         add_sent_category=True)
        add_fake_message(db.session, default_account.namespace.id, thread,
                         subject=test_subject, received_date=date3)
        add_fake_message(db.session, default_account.namespace.id, thread,
                         subject=test_subject, received_date=date4,
                         add_sent_category=True)
        add_fake_message(db.session, default_account.namespace.id, thread,
                         subject=test_subject, received_date=date5)

    resp = api_client.get_raw('/threads/?view=count&in=sent')
    assert resp.status_code == 200
    threads = json.loads(resp.data)
    assert threads['count'] == 2
Example #2
0
def test_basic_message_grouping(db, default_namespace):
    first_thread = add_fake_thread(db.session, default_namespace.id)
    first_thread.subject = 'Some kind of test'

    add_fake_message(db.session, default_namespace.id,
                     thread=first_thread,
                     subject='Some kind of test',
                     from_addr=[('Karim Hamidou', '*****@*****.**')],
                     to_addr=[('Eben Freeman', '*****@*****.**')],
                     bcc_addr=[('Some person', '*****@*****.**')])

    msg2 = add_fake_message(db.session, default_namespace.id, thread=None,
                            subject='Re: Some kind of test',
                            from_addr=[('Some random dude',
                                        '*****@*****.**')],
                            to_addr=[('Karim Hamidou', '*****@*****.**')])

    matched_thread = fetch_corresponding_thread(db.session,
                                                default_namespace.id, msg2)
    assert matched_thread is None, "the algo shouldn't thread different convos"

    msg3 = add_fake_message(db.session, default_namespace.id, thread=None)
    msg3.subject = 'Re: Some kind of test'
    msg3.from_addr = [('Eben Freeman', '*****@*****.**')]
    msg3.to_addr = [('Karim Hamidou', '*****@*****.**')]

    matched_thread = fetch_corresponding_thread(db.session, default_namespace.id, msg3)
    assert matched_thread is first_thread, "Should match on participants"
def test_generic_grouping(db, default_account):
    thread = add_fake_thread(db.session, default_account.namespace.id)
    message = add_fake_message(db.session,
                               default_account.namespace.id,
                               thread,
                               subject="Golden Gate Park next Sat")
    folder = Folder(account=default_account,
                    name='Inbox',
                    canonical_name='inbox')
    ImapUid(message=message,
            account_id=default_account.id,
            msg_uid=2222,
            folder=folder)

    thread = add_fake_thread(db.session, default_account.namespace.id)

    account = add_generic_imap_account(db.session)
    message = add_fake_message(db.session,
                               account.namespace.id,
                               thread,
                               subject="Golden Gate Park next Sat")

    thread = fetch_corresponding_thread(db.session,
                                        default_account.namespace.id, message)
    assert thread is None, ("fetch_similar_threads should "
                            "heed namespace boundaries")
def test_namespace_deletion(db, default_account):
    from inbox.models import Account, Thread, Message
    from inbox.models.util import delete_namespace

    models = [Thread, Message]

    namespace = default_account.namespace
    namespace_id = namespace.id
    account_id = default_account.id

    account = db.session.query(Account).get(account_id)
    assert account

    thread = add_fake_thread(db.session, namespace_id)

    message = add_fake_message(db.session, namespace_id, thread)

    for m in models:
        c = db.session.query(m).filter(m.namespace_id == namespace_id).count()
        print "count for", m, ":", c
        assert c != 0

    fake_account = add_generic_imap_account(db.session)
    fake_account_id = fake_account.id

    assert fake_account_id != account.id and \
        fake_account.namespace.id != namespace_id

    thread = add_fake_thread(db.session, fake_account.namespace.id)
    thread_id = thread.id

    message = add_fake_message(db.session, fake_account.namespace.id, thread)
    message_id = message.id

    assert len(
        db.session.query(Namespace).filter(
            Namespace.id == namespace_id).all()) > 0

    # Delete namespace, verify data corresponding to this namespace /only/
    # is deleted
    delete_namespace(account_id, namespace_id)
    db.session.commit()

    assert len(
        db.session.query(Namespace).filter(
            Namespace.id == namespace_id).all()) == 0

    account = db.session.query(Account).get(account_id)
    assert not account

    for m in models:
        assert db.session.query(m).filter(
            m.namespace_id == namespace_id).count() == 0

    fake_account = db.session.query(Account).get(fake_account_id)
    assert fake_account

    thread = db.session.query(Thread).get(thread_id)
    message = db.session.query(Message).get(message_id)
    assert thread and message
def test_update_contacts_from_message(db, default_namespace, thread):
    # Check that only one Contact is created for repeatedly-referenced
    # addresses.
    add_fake_message(db.session,
                     default_namespace.id,
                     thread,
                     from_addr=[('', '*****@*****.**')],
                     cc_addr=[('', '*****@*****.**')])

    assert db.session.query(Contact).filter_by(
        email_address='*****@*****.**').count() == 1

    # Check that existing Contacts are used when we process a new message
    # referencing them.
    add_fake_message(db.session,
                     default_namespace.id,
                     thread,
                     from_addr=[('', '*****@*****.**')],
                     cc_addr=[('', '*****@*****.**')],
                     to_addr=[('', '*****@*****.**'),
                              ('', '*****@*****.**')])

    assert db.session.query(Contact).filter(
        Contact.email_address.like('*****@*****.**'),
        Contact.namespace_id == default_namespace.id).count() == 3
    alpha = db.session.query(Contact).filter_by(
        email_address='*****@*****.**',
        namespace_id=default_namespace.id).one()
    assert len(alpha.message_associations) == 4
Example #6
0
def test_namespace_limiting(db, api_client, default_namespaces):
    dt = datetime.datetime.utcnow()
    subject = dt.isoformat()
    namespaces = db.session.query(Namespace).all()
    assert len(namespaces) > 1
    for ns in namespaces:
        thread = Thread(namespace=ns,
                        subjectdate=dt,
                        recentdate=dt,
                        subject=subject)
        add_fake_message(db.session,
                         ns.id,
                         thread,
                         received_date=dt,
                         subject=subject)
        db.session.add(Block(namespace=ns, filename=subject))
    db.session.commit()

    for ns in namespaces:
        r = api_client.get_data('/threads?subject={}'.format(subject))
        assert len(r) == 1

        r = api_client.get_data('/messages?subject={}'.format(subject))
        assert len(r) == 1

        r = api_client.get_data('/files?filename={}'.format(subject))
        assert len(r) == 1
Example #7
0
def test_update_contacts_from_message(db, default_namespace, thread):
    # Check that only one Contact is created for repeatedly-referenced
    # addresses.
    add_fake_message(db.session, default_namespace.id, thread,
                     from_addr=[('', '*****@*****.**')],
                     cc_addr=[('', '*****@*****.**')])

    assert db.session.query(Contact).filter_by(
        email_address='*****@*****.**').count() == 1

    # Check that existing Contacts are used when we process a new message
    # referencing them.
    add_fake_message(db.session, default_namespace.id, thread,
                     from_addr=[('', '*****@*****.**')],
                     cc_addr=[('', '*****@*****.**')],
                     to_addr=[('', '*****@*****.**'),
                              ('', '*****@*****.**')])

    assert db.session.query(Contact).filter(
        Contact.email_address.like('*****@*****.**'),
        Contact.namespace_id == default_namespace.id).count() == 3
    alpha = db.session.query(Contact).filter_by(
        email_address='*****@*****.**',
        namespace_id=default_namespace.id).one()
    assert len(alpha.message_associations) == 4
Example #8
0
def test_thread_sent_recent_date(db, api_client, default_account):
    date1 = datetime.datetime(2015, 1, 1, 0, 0, 0)
    date2 = datetime.datetime(2012, 1, 1, 0, 0, 0)
    date3 = datetime.datetime(2010, 1, 1, 0, 0, 0)
    date4 = datetime.datetime(2009, 1, 1, 0, 0, 0)
    date5 = datetime.datetime(2008, 1, 1, 0, 0, 0)

    thread1 = add_fake_thread(db.session, default_account.namespace.id)

    test_subject = "test_thread_sent_recent_date"

    add_fake_message(db.session, default_account.namespace.id, thread1,
                     subject=test_subject, received_date=date1)
    add_fake_message(db.session, default_account.namespace.id, thread1,
                     subject=test_subject, received_date=date2,
                     add_sent_category=True)
    add_fake_message(db.session, default_account.namespace.id, thread1,
                     subject=test_subject, received_date=date3)
    add_fake_message(db.session, default_account.namespace.id, thread1,
                     subject=test_subject, received_date=date4,
                     add_sent_category=True)
    add_fake_message(db.session, default_account.namespace.id, thread1,
                     subject=test_subject, received_date=date5)

    resp = api_client.get_raw('/threads/')
    assert resp.status_code == 200
    threads = json.loads(resp.data)

    for thread in threads:  # should only be one
        assert datetime.datetime.fromtimestamp(
            thread['last_message_sent_timestamp']) == date2
Example #9
0
def test_basic_message_grouping(db, default_namespace):
    first_thread = add_fake_thread(db.session, default_namespace.id)
    first_thread.subject = 'Some kind of test'

    add_fake_message(db.session,
                     default_namespace.id,
                     thread=first_thread,
                     subject='Some kind of test',
                     from_addr=[('Karim Hamidou', '*****@*****.**')],
                     to_addr=[('Eben Freeman', '*****@*****.**')],
                     bcc_addr=[('Some person', '*****@*****.**')])

    msg2 = add_fake_message(db.session,
                            default_namespace.id,
                            thread=None,
                            subject='Re: Some kind of test',
                            from_addr=[('Some random dude', '*****@*****.**')
                                       ],
                            to_addr=[('Karim Hamidou', '*****@*****.**')])

    matched_thread = fetch_corresponding_thread(db.session,
                                                default_namespace.id, msg2)
    assert matched_thread is None, "the algo shouldn't thread different convos"

    msg3 = add_fake_message(db.session, default_namespace.id, thread=None)
    msg3.subject = 'Re: Some kind of test'
    msg3.from_addr = [('Eben Freeman', '*****@*****.**')]
    msg3.to_addr = [('Karim Hamidou', '*****@*****.**')]

    matched_thread = fetch_corresponding_thread(db.session,
                                                default_namespace.id, msg3)
    assert matched_thread is first_thread, "Should match on participants"
Example #10
0
def test_namespace_deletion(db, default_account):
    from inbox.models import Account, Thread, Message
    from inbox.models.util import delete_namespace

    models = [Thread, Message]

    namespace = default_account.namespace
    namespace_id = namespace.id
    account_id = default_account.id

    account = db.session.query(Account).get(account_id)
    assert account

    thread = add_fake_thread(db.session, namespace_id)

    message = add_fake_message(db.session, namespace_id, thread)

    for m in models:
        c = db.session.query(m).filter(
            m.namespace_id == namespace_id).count()
        print "count for", m, ":", c
        assert c != 0

    fake_account = add_generic_imap_account(db.session)
    fake_account_id = fake_account.id

    assert fake_account_id != account.id and \
        fake_account.namespace.id != namespace_id

    thread = add_fake_thread(db.session, fake_account.namespace.id)
    thread_id = thread.id

    message = add_fake_message(db.session, fake_account.namespace.id, thread)
    message_id = message.id

    assert len(db.session.query(Namespace).filter(Namespace.id == namespace_id).all()) > 0

    # Delete namespace, verify data corresponding to this namespace /only/
    # is deleted
    delete_namespace(account_id, namespace_id)
    db.session.commit()

    assert len(db.session.query(Namespace).filter(Namespace.id == namespace_id).all()) == 0

    account = db.session.query(Account).get(account_id)
    assert not account

    for m in models:
        assert db.session.query(m).filter(
            m.namespace_id == namespace_id).count() == 0

    fake_account = db.session.query(Account).get(fake_account_id)
    assert fake_account

    thread = db.session.query(Thread).get(thread_id)
    message = db.session.query(Message).get(message_id)
    assert thread and message
def test_handle_noreply_addresses(db, default_namespace, thread):
    add_fake_message(db.session,
                     default_namespace.id,
                     thread,
                     from_addr=[('Alice', '*****@*****.**')])
    add_fake_message(db.session,
                     default_namespace.id,
                     thread,
                     from_addr=[('Bob', '*****@*****.**')])

    noreply_contact = db.session.query(Contact).filter(
        Contact.namespace == default_namespace,
        Contact.email_address == '*****@*****.**').one()
    assert noreply_contact.name is None

    add_fake_message(db.session,
                     default_namespace.id,
                     thread,
                     from_addr=[('Alice', '*****@*****.**')])
    add_fake_message(db.session,
                     default_namespace.id,
                     thread,
                     from_addr=[('Alice Lastname', '*****@*****.**')])

    contact = db.session.query(Contact).filter(
        Contact.namespace == default_namespace,
        Contact.email_address == '*****@*****.**').first()
    assert contact.name is not None
def test_transaction_creation_for_self_referential_message_relationship(db, default_namespace):
    # Make sure that updating the self-refential relationship
    # `Message.reply_to_message` does not create a spurious update delta for
    # the parent message.
    thr = add_fake_thread(db.session, default_namespace.id)
    msg = add_fake_message(db.session, default_namespace.id, thr)
    reply = add_fake_message(db.session, default_namespace.id, thr)
    reply.reply_to_message = msg
    db.session.commit()
    assert reply.reply_to_message_id is not None
    assert msg.reply_to_message_id is None
    transaction = get_latest_transaction(db.session, "message", msg.id, default_namespace.id)
    assert transaction.record_id == msg.id
    assert transaction.object_type == "message"
    assert transaction.command == "insert"
Example #13
0
def test_label_delete(db, gmail_account, label_client, api_version):
    headers = dict()
    headers['Api-Version'] = api_version

    # Make a new message
    gmail_thread = add_fake_thread(db.session, gmail_account.namespace.id)
    gmail_message = add_fake_message(db.session, gmail_account.namespace.id,
                                     gmail_thread)
    g_data = label_client.get_raw('/labels/', headers=headers)
    # Add label to message
    gmail_label = json.loads(g_data.data)[0]
    data = {"labels": [gmail_label['id']]}
    label_client.put_data('/messages/{}'.format(gmail_message.public_id),
                          data,
                          headers=headers)

    # DELETE requests should work on labels whether or not messages have them
    d_data = label_client.delete('/labels/{}'.format(gmail_label['id']),
                                 headers=headers)
    assert d_data.status_code == 200

    if api_version == API_VERSIONS[0]:
        # Optimistic update.
        category_id = gmail_label['id']
        category = db.session.query(Category).filter(
            Category.public_id == category_id).one()
        assert category.deleted_at != EPOCH
        assert category.is_deleted is True
Example #14
0
def test_folder_delete(db, generic_account, folder_client, api_version):
    headers = dict()
    headers['Api-Version'] = api_version

    # Make a new message
    generic_thread = add_fake_thread(db.session, generic_account.namespace.id)
    gen_message = add_fake_message(db.session, generic_account.namespace.id,
                                   generic_thread)
    g_data = folder_client.get_raw('/folders/')
    # Add message to folder
    generic_folder = json.loads(g_data.data)[0]
    data = {"folder_id": generic_folder['id']}
    folder_client.put_data('/messages/{}'.format(gen_message.public_id), data)

    # Test that DELETE requests 403 on folders with items in them
    d_data = folder_client.delete('/folders/{}'.format(generic_folder['id']))
    assert d_data.status_code == 400

    # Make an empty folder
    resp = folder_client.post_data('/folders/',
                                   {"display_name": "Empty_Folder"})
    empty_folder = json.loads(resp.data)
    # Test that DELETE requests delete empty folders
    d_data = folder_client.delete('/folders/{}'.format(empty_folder['id']))
    assert d_data.status_code == 200

    if api_version == API_VERSIONS[0]:
        # Did we update things optimistically?
        category_id = empty_folder['id']
        category = db.session.query(Category).filter(
            Category.public_id == category_id).one()
        assert category.deleted_at != EPOCH
        assert category.is_deleted is True

    db.session.rollback()
Example #15
0
def test_label_delete(db, gmail_account, label_client, api_version):
    headers = dict()
    headers['Api-Version'] = api_version

    # Make a new message
    gmail_thread = add_fake_thread(db.session, gmail_account.namespace.id)
    gmail_message = add_fake_message(db.session,
                                     gmail_account.namespace.id, gmail_thread)
    g_data = label_client.get_raw('/labels/', headers=headers)
    # Add label to message
    gmail_label = json.loads(g_data.data)[0]
    data = {"labels": [gmail_label['id']]}
    label_client.put_data('/messages/{}'.format(gmail_message.public_id), data,
                          headers=headers)

    # DELETE requests should work on labels whether or not messages have them
    d_data = label_client.delete('/labels/{}'.format(gmail_label['id']),
                                 headers=headers)
    assert d_data.status_code == 200

    if api_version == API_VERSIONS[0]:
        # Optimistic update.
        category_id = gmail_label['id']
        category = db.session.query(Category).filter(
            Category.public_id == category_id).one()
        assert category.deleted_at != EPOCH
        assert category.is_deleted is True
def test_message_updates_create_thread_transaction(db, default_namespace):
    with db.session.no_autoflush:
        thr = add_fake_thread(db.session, default_namespace.id)
        msg = add_fake_message(db.session, default_namespace.id, thr)

        transaction = get_latest_transaction(db.session, "thread", thr.id, default_namespace.id)
        assert transaction.record_id == thr.id and transaction.object_type == "thread"
        assert transaction.command == "update"

        # An update to one of the message's propagated_attributes creates a
        # revision for the thread
        msg.is_read = True
        db.session.commit()

        new_transaction = get_latest_transaction(db.session, "thread", thr.id, default_namespace.id)
        assert new_transaction.id != transaction.id
        assert new_transaction.record_id == thr.id and new_transaction.object_type == "thread"
        assert new_transaction.command == "update"

        # An update to one of its other attributes does not
        msg.subject = "Ice cubes and dogs"
        db.session.commit()

        same_transaction = get_latest_transaction(db.session, "thread", thr.id, default_namespace.id)
        assert same_transaction.id == new_transaction.id
def test_message_delete(db, gmail_account):
    """ Ensure that all associated MessageCategories are deleted
        when a Message is deleted """

    api_client = new_api_client(db, gmail_account.namespace)

    generic_thread = add_fake_thread(db.session, gmail_account.namespace.id)
    gen_message = add_fake_message(db.session, gmail_account.namespace.id,
                                   generic_thread)

    category_ids = []
    for i in xrange(10):
        po_data = api_client.post_data('/labels/', {"display_name": str(i)})
        assert po_data.status_code == 200

        category_ids.append(json.loads(po_data.data)['id'])

    data = {"label_ids": category_ids}
    resp = api_client.put_data('/messages/{}'.format(gen_message.public_id),
                               data)
    assert resp.status_code == 200

    associated_mcs = db.session.query(MessageCategory). \
        filter(MessageCategory.message_id == gen_message.id).all()
    assert len(associated_mcs) == 10

    db.session.delete(gen_message)
    db.session.commit()

    assert db.session.query(MessageCategory). \
        filter(MessageCategory.message_id == gen_message.id).all() == []
Example #18
0
def test_message_label_updates(db, api_client, default_account, api_version,
                               custom_label):
    """Check that you can update a message (optimistically or not),
    and that the update is queued in the ActionLog."""

    headers = dict()
    headers['Api-Version'] = api_version

    # Gmail threads, messages have a 'labels' field
    gmail_thread = add_fake_thread(db.session, default_account.namespace.id)
    gmail_message = add_fake_message(db.session, default_account.namespace.id,
                                     gmail_thread)

    resp_data = api_client.get_data('/messages/{}'.format(
        gmail_message.public_id),
                                    headers=headers)

    assert resp_data['labels'] == []

    category = custom_label.category
    update = dict(labels=[category.public_id])

    resp = api_client.put_data('/messages/{}'.format(gmail_message.public_id),
                               update,
                               headers=headers)

    resp_data = json.loads(resp.data)

    if api_version == API_VERSIONS[0]:
        assert len(resp_data['labels']) == 1
        assert resp_data['labels'][0]['id'] == category.public_id
    else:
        assert resp_data['labels'] == []
Example #19
0
def test_message_updates_create_thread_transaction(db, default_namespace):
    with db.session.no_autoflush:
        thr = add_fake_thread(db.session, default_namespace.id)
        msg = add_fake_message(db.session, default_namespace.id, thr)

        transaction = get_latest_transaction(db.session, 'thread', thr.id,
                                             default_namespace.id)
        assert (transaction.record_id == thr.id
                and transaction.object_type == 'thread')
        assert transaction.command == 'update'

        # An update to one of the message's propagated_attributes creates a
        # revision for the thread
        msg.is_read = True
        db.session.commit()

        new_transaction = get_latest_transaction(db.session, 'thread', thr.id,
                                                 default_namespace.id)
        assert new_transaction.id != transaction.id
        assert (new_transaction.record_id == thr.id
                and new_transaction.object_type == 'thread')
        assert new_transaction.command == 'update'

        # An update to one of its other attributes does not
        msg.subject = 'Ice cubes and dogs'
        db.session.commit()

        same_transaction = get_latest_transaction(db.session, 'thread', thr.id,
                                                  default_namespace.id)
        assert same_transaction.id == new_transaction.id
Example #20
0
def test_category_delete(db, gmail_account):
    """ Ensure that all associated MessageCategories are deleted
        when a Category is deleted """

    api_client = new_api_client(db, gmail_account.namespace)
    po_data = api_client.post_data('/labels/',
                                   {"display_name": "Test_Label"})
    assert po_data.status_code == 200

    category_public_id = json.loads(po_data.data)['id']
    category = db.session.query(Category).filter(
        Category.public_id == category_public_id).one()
    category_id = category.id

    for i in xrange(10):
        generic_thread = add_fake_thread(db.session,
                                         gmail_account.namespace.id)
        gen_message = add_fake_message(db.session,
                                       gmail_account.namespace.id,
                                       generic_thread)
        data = {"label_ids": [category_public_id]}
        resp = api_client.put_data('/messages/{}'.
                                   format(gen_message.public_id), data)
        assert resp.status_code == 200

    associated_mcs = db.session.query(MessageCategory). \
        filter(MessageCategory.category_id == category_id).all()
    assert len(associated_mcs) == 10

    db.session.delete(category)
    db.session.commit()

    assert db.session.query(MessageCategory). \
        filter(MessageCategory.category_id == category_id).all() == []
Example #21
0
def test_message_delete(db, gmail_account):
    """ Ensure that all associated MessageCategories are deleted
        when a Message is deleted """

    api_client = new_api_client(db, gmail_account.namespace)

    generic_thread = add_fake_thread(db.session, gmail_account.namespace.id)
    gen_message = add_fake_message(db.session,
                                   gmail_account.namespace.id,
                                   generic_thread)

    category_ids = []
    for i in xrange(10):
        po_data = api_client.post_data('/labels/',
                                       {"display_name": str(i)})
        assert po_data.status_code == 200

        category_ids.append(json.loads(po_data.data)['id'])

    data = {"label_ids": category_ids}
    resp = api_client.put_data('/messages/{}'.
                               format(gen_message.public_id), data)
    assert resp.status_code == 200

    associated_mcs = db.session.query(MessageCategory). \
        filter(MessageCategory.message_id == gen_message.id).all()
    assert len(associated_mcs) == 10

    db.session.delete(gen_message)
    db.session.commit()

    assert db.session.query(MessageCategory). \
        filter(MessageCategory.message_id == gen_message.id).all() == []
Example #22
0
def test_message_label_updates(db, api_client, default_account, api_version,
                               custom_label):
    """Check that you can update a message (optimistically or not),
    and that the update is queued in the ActionLog."""

    headers = dict()
    headers['Api-Version'] = api_version

    # Gmail threads, messages have a 'labels' field
    gmail_thread = add_fake_thread(db.session, default_account.namespace.id)
    gmail_message = add_fake_message(db.session,
                                     default_account.namespace.id, gmail_thread)

    resp_data = api_client.get_data(
        '/messages/{}'.format(gmail_message.public_id), headers=headers)

    assert resp_data['labels'] == []

    category = custom_label.category
    update = dict(labels=[category.public_id])

    resp = api_client.put_data(
        '/messages/{}'.format(gmail_message.public_id), update,
                              headers=headers)

    resp_data = json.loads(resp.data)

    if api_version == API_VERSIONS[0]:
        assert len(resp_data['labels']) == 1
        assert resp_data['labels'][0]['id'] == category.public_id
    else:
        assert resp_data['labels'] == []
def test_category_delete(db, gmail_account):
    """ Ensure that all associated MessageCategories are deleted
        when a Category is deleted """

    api_client = new_api_client(db, gmail_account.namespace)
    po_data = api_client.post_data('/labels/', {"display_name": "Test_Label"})
    assert po_data.status_code == 200

    category_public_id = json.loads(po_data.data)['id']
    category = db.session.query(Category).filter(
        Category.public_id == category_public_id).one()
    category_id = category.id

    for i in xrange(10):
        generic_thread = add_fake_thread(db.session,
                                         gmail_account.namespace.id)
        gen_message = add_fake_message(db.session, gmail_account.namespace.id,
                                       generic_thread)
        data = {"label_ids": [category_public_id]}
        resp = api_client.put_data(
            '/messages/{}'.format(gen_message.public_id), data)
        assert resp.status_code == 200

    associated_mcs = db.session.query(MessageCategory). \
        filter(MessageCategory.category_id == category_id).all()
    assert len(associated_mcs) == 10

    db.session.delete(category)
    db.session.commit()

    assert db.session.query(MessageCategory). \
        filter(MessageCategory.category_id == category_id).all() == []
Example #24
0
def test_reject_incompatible_reply_thread_and_message(
        db, api_client, message, thread, default_namespace):
    alt_thread = add_fake_thread(db.session, default_namespace.id)
    add_fake_message(db.session, default_namespace.id, alt_thread)

    thread = api_client.get_data('/threads')[0]
    alt_message_id = api_client.get_data('/threads')[1]['message_ids'][0]
    alt_message = api_client.get_data('/messages/{}'.format(alt_message_id))
    assert thread['id'] != alt_message['thread_id']
    reply_draft = {
        'subject': 'test reply',
        'reply_to_message_id': alt_message['id'],
        'thread_id': thread['id']
    }
    r = api_client.post_data('/drafts', reply_draft)
    assert r.status_code == 400
Example #25
0
def test_reject_incompatible_reply_thread_and_message(db, api_client, message,
                                                      thread,
                                                      default_namespace):
    alt_thread = add_fake_thread(db.session, default_namespace.id)
    add_fake_message(db.session, default_namespace.id, alt_thread)

    thread = api_client.get_data('/threads')[0]
    alt_message_id = api_client.get_data('/threads')[1]['message_ids'][0]
    alt_message = api_client.get_data('/messages/{}'.format(alt_message_id))
    assert thread['id'] != alt_message['thread_id']
    reply_draft = {
        'subject': 'test reply',
        'reply_to_message_id': alt_message['id'],
        'thread_id': thread['id']
    }
    r = api_client.post_data('/drafts', reply_draft)
    assert r.status_code == 400
Example #26
0
def test_thread_sent_recent_date(db, api_client, default_account):
    date1 = datetime.datetime(2015, 1, 1, 0, 0, 0)
    date2 = datetime.datetime(2012, 1, 1, 0, 0, 0)
    date3 = datetime.datetime(2010, 1, 1, 0, 0, 0)
    date4 = datetime.datetime(2009, 1, 1, 0, 0, 0)
    date5 = datetime.datetime(2008, 1, 1, 0, 0, 0)

    thread1 = add_fake_thread(db.session, default_account.namespace.id)

    test_subject = "test_thread_sent_recent_date"

    add_fake_message(db.session,
                     default_account.namespace.id,
                     thread1,
                     subject=test_subject,
                     received_date=date1)
    add_fake_message(db.session,
                     default_account.namespace.id,
                     thread1,
                     subject=test_subject,
                     received_date=date2,
                     add_sent_category=True)
    add_fake_message(db.session,
                     default_account.namespace.id,
                     thread1,
                     subject=test_subject,
                     received_date=date3)
    add_fake_message(db.session,
                     default_account.namespace.id,
                     thread1,
                     subject=test_subject,
                     received_date=date4,
                     add_sent_category=True)
    add_fake_message(db.session,
                     default_account.namespace.id,
                     thread1,
                     subject=test_subject,
                     received_date=date5)

    resp = api_client.get_raw('/threads/')
    assert resp.status_code == 200
    threads = json.loads(resp.data)

    for thread in threads:  # should only be one
        assert datetime.datetime.fromtimestamp(
            thread['last_message_sent_timestamp']) == date2
Example #27
0
def test_adding_and_removing_message_on_thread_increments_version(
        db, thread, default_namespace):
    assert thread.version == 0
    message = add_fake_message(db.session, default_namespace.id, thread)
    assert thread.version == 1
    thread.messages.remove(message)
    db.session.commit()
    assert thread.version == 2
Example #28
0
def different_imap_messages(db, generic_account, different_sorted_imap_threads,
                            different_imap_folder):
    thread1, thread2, thread3 = different_sorted_imap_threads
    message1 = add_fake_message(db.session, generic_account.namespace.id,
                                thread=thread1,
                                from_addr=[{'name': '',
                                            'email':
                                            '*****@*****.**'}],
                                to_addr=[{'name': 'Ben Bitdiddle',
                                          'email': '*****@*****.**'}],
                                received_date=datetime.
                                datetime(2015, 7, 9, 23, 50, 7),
                                subject='LOL')

    add_fake_imapuid(db.session, generic_account.id, message1,
                     different_imap_folder, 5000)

    message2 = add_fake_message(db.session, generic_account.namespace.id,
                                thread=thread2,
                                from_addr=[{'name': '',
                                            'email':
                                            '*****@*****.**'}],
                                to_addr=[{'name': 'Ben Bitdiddle',
                                          'email': '*****@*****.**'}],
                                received_date=datetime.
                                datetime(2014, 7, 9, 23, 50, 7),
                                subject='ROTFLMO')

    add_fake_imapuid(db.session, generic_account.id, message2,
                     different_imap_folder, 5001)

    message3 = add_fake_message(db.session, generic_account.namespace.id,
                                thread=thread3,
                                from_addr=[{'name': '',
                                            'email':
                                            '*****@*****.**'}],
                                to_addr=[{'name': 'Ben Bitdiddle',
                                          'email': '*****@*****.**'}],
                                received_date=datetime.
                                datetime(2013, 7, 9, 23, 50, 7),
                                subject='ROFLCOPTER')

    add_fake_imapuid(db.session, generic_account.id, message3,
                     different_imap_folder, 5002)

    return [message1, message2, message3]
Example #29
0
def test_transaction_creation_for_self_referential_message_relationship(
        db, default_namespace):
    # Make sure that updating the self-refential relationship
    # `Message.reply_to_message` does not create a spurious update delta for
    # the parent message.
    thr = add_fake_thread(db.session, default_namespace.id)
    msg = add_fake_message(db.session, default_namespace.id, thr)
    reply = add_fake_message(db.session, default_namespace.id, thr)
    reply.reply_to_message = msg
    db.session.commit()
    assert reply.reply_to_message_id is not None
    assert msg.reply_to_message_id is None
    transaction = get_latest_transaction(db.session, 'message', msg.id,
                                         default_namespace.id)
    assert transaction.record_id == msg.id
    assert transaction.object_type == 'message'
    assert transaction.command == 'insert'
Example #30
0
def sorted_imap_messages(db, generic_account, sorted_imap_threads, imap_folder):
    thread1, thread2, thread3 = sorted_imap_threads
    message1 = add_fake_message(db.session, generic_account.namespace.id,
                                thread=thread1,
                                from_addr=[{'name': '',
                                            'email':
                                            '*****@*****.**'}],
                                to_addr=[{'name': 'Ben Bitdiddle',
                                          'email': '*****@*****.**'}],
                                received_date=datetime.
                                datetime(2015, 7, 9, 23, 50, 7),
                                subject='YOO!')

    add_fake_imapuid(db.session, generic_account.id, message1,
                     imap_folder, 2000)

    message2 = add_fake_message(db.session, generic_account.namespace.id,
                                thread=thread2,
                                from_addr=[{'name': '',
                                            'email':
                                            '*****@*****.**'}],
                                to_addr=[{'name': 'Ben Bitdiddle',
                                          'email': '*****@*****.**'}],
                                received_date=datetime.
                                datetime(2014, 7, 9, 23, 50, 7),
                                subject='Hey!')

    add_fake_imapuid(db.session, generic_account.id, message2,
                     imap_folder, 2001)

    message3 = add_fake_message(db.session, generic_account.namespace.id,
                                thread=thread3,
                                from_addr=[{'name': '',
                                            'email':
                                            '*****@*****.**'}],
                                to_addr=[{'name': 'Ben Bitdiddle',
                                          'email': '*****@*****.**'}],
                                received_date=datetime.
                                datetime(2013, 7, 9, 23, 50, 7),
                                subject='Sup?')

    add_fake_imapuid(db.session, generic_account.id, message3,
                     imap_folder, 2002)

    return [message1, message2, message3]
Example #31
0
def sorted_gmail_messages(db, default_account, sorted_gmail_threads, folder):
    thread1, thread2, thread3 = sorted_gmail_threads
    message1 = add_fake_message(db.session, default_account.namespace.id,
                                thread=thread1,
                                g_msgid=1,
                                from_addr=[{'name': 'Ben Bitdiddle',
                                            'email': '*****@*****.**'}],
                                to_addr=[{'name': 'Barrack Obama',
                                          'email': '*****@*****.**'}],
                                received_date=datetime.
                                datetime(2015, 7, 9, 23, 50, 7),
                                subject='YOO!')

    add_fake_imapuid(db.session, default_account.id, message1,
                     folder, 3000)

    message2 = add_fake_message(db.session, default_account.namespace.id,
                                thread=thread2,
                                g_msgid=2,
                                from_addr=[{'name': 'Ben Bitdiddle',
                                            'email': '*****@*****.**'}],
                                to_addr=[{'name': 'Barrack Obama',
                                          'email': '*****@*****.**'}],
                                received_date=datetime.
                                datetime(2014, 7, 9, 23, 50, 7),
                                subject='Hey!')

    add_fake_imapuid(db.session, default_account.id, message2,
                     folder, 3001)

    message3 = add_fake_message(db.session, default_account.namespace.id,
                                thread=thread3,
                                g_msgid=3,
                                from_addr=[{'name': 'Ben Bitdiddle',
                                            'email': '*****@*****.**'}],
                                to_addr=[{'name': 'Barrack Obama',
                                          'email': '*****@*****.**'}],
                                received_date=datetime.
                                datetime(2013, 7, 9, 23, 50, 7),
                                subject='Sup?')

    add_fake_imapuid(db.session, default_account.id, message3,
                     folder, 3002)

    return [message1, message2, message3]
Example #32
0
def stub_message(db, new_message_from_synced, default_namespace, thread):
    message = add_fake_message(db.session,
                               default_namespace.id,
                               thread,
                               subject="Golden Gate Park next Sat",
                               from_addr=[('alice', '*****@*****.**')],
                               to_addr=[('bob', '*****@*****.**')])
    message.snippet = 'Banh mi paleo pickled, sriracha'
    message.body = """
Banh mi paleo pickled, sriracha biodiesel chambray seitan
mumblecore mustache. Raw denim gastropub 8-bit, butcher
PBR sartorial photo booth Pinterest blog Portland roof party
cliche bitters aesthetic. Ugh.
"""

    message = add_fake_message(db.session,
                               default_namespace.id,
                               thread,
                               subject="Re:Golden Gate Park next Sat",
                               from_addr=[('bob', '*****@*****.**')],
                               to_addr=[('alice', '*****@*****.**')],
                               cc_addr=[('Cheryl', '*****@*****.**')])
    message.snippet = 'Bushwick meggings ethical keffiyeh'
    message.body = """
Bushwick meggings ethical keffiyeh. Chambray lumbersexual wayfarers,
irony Banksy cred bicycle rights scenester artisan tote bag YOLO gastropub.
"""

    draft = add_fake_message(db.session,
                             default_namespace.id,
                             thread,
                             subject="Re:Golden Gate Park next Sat",
                             from_addr=[('alice', '*****@*****.**')],
                             to_addr=[('bob', '*****@*****.**')],
                             cc_addr=[('Cheryl', '*****@*****.**')])
    draft.snippet = 'Hey there friend writing a draft'
    draft.body = """
DIY tousled Tumblr, VHS meditation 3 wolf moon listicle fingerstache viral
bicycle rights. Thundercats kale chips church-key American Apparel.
"""
    draft.is_draft = True
    draft.reply_to_message = message

    db.session.commit()
    return message
Example #33
0
def test_namespace_delete_cascade(db, default_account):
    from inbox.models import Account, Thread, Message

    models = [Thread, Message]

    namespace = default_account.namespace
    namespace_id = namespace.id
    account_id = default_account.id

    account = db.session.query(Account).get(account_id)
    assert account

    thread = add_fake_thread(db.session, namespace_id)

    add_fake_message(db.session, namespace_id, thread)

    for m in models:
        c = db.session.query(m).filter(m.namespace_id == namespace_id).count()
        print "count for", m, ":", c
        assert c != 0

    fake_account = add_generic_imap_account(db.session)
    fake_account_id = fake_account.id

    assert fake_account_id != account.id and \
        fake_account.namespace.id != namespace_id

    thread = add_fake_thread(db.session, fake_account.namespace.id)

    add_fake_message(db.session, fake_account.namespace.id, thread)

    assert len(
        db.session.query(Namespace).filter(
            Namespace.id == namespace_id).all()) > 0

    # This test is separate from test_namespace_deletion because we want to
    # do a raw SQLAlchemy delete rather than using delete_namespace, which does
    # a bunch of extra work to ensure that objects associated with a Namespace
    # are actually deleted.
    db.session.query(Namespace).filter(Namespace.id == namespace_id).delete()
    db.session.commit()

    assert len(
        db.session.query(Namespace).filter(
            Namespace.id == namespace_id).all()) == 0
Example #34
0
def test_thread_count(db, api_client, default_account):
    date1 = datetime.datetime(2015, 1, 1, 0, 0, 0)
    date2 = datetime.datetime(2012, 1, 1, 0, 0, 0)
    date3 = datetime.datetime(2010, 1, 1, 0, 0, 0)
    date4 = datetime.datetime(2009, 1, 1, 0, 0, 0)
    date5 = datetime.datetime(2008, 1, 1, 0, 0, 0)

    thread1 = add_fake_thread(db.session, default_account.namespace.id)
    thread2 = add_fake_thread(db.session, default_account.namespace.id)

    test_subject = "test_thread_view_count_with_category"

    for thread in [thread1, thread2]:
        add_fake_message(db.session,
                         default_account.namespace.id,
                         thread,
                         subject=test_subject,
                         received_date=date1)
        add_fake_message(db.session,
                         default_account.namespace.id,
                         thread,
                         subject=test_subject,
                         received_date=date2,
                         add_sent_category=True)
        add_fake_message(db.session,
                         default_account.namespace.id,
                         thread,
                         subject=test_subject,
                         received_date=date3)
        add_fake_message(db.session,
                         default_account.namespace.id,
                         thread,
                         subject=test_subject,
                         received_date=date4,
                         add_sent_category=True)
        add_fake_message(db.session,
                         default_account.namespace.id,
                         thread,
                         subject=test_subject,
                         received_date=date5)

    resp = api_client.get_raw('/threads/?view=count&in=sent')
    assert resp.status_code == 200
    threads = json.loads(resp.data)
    assert threads['count'] == 2
Example #35
0
def test_distinct_results(api_client, db, default_namespace):
    """Test that limit and offset parameters work correctly when joining on
    multiple matching messages per thread."""
    # Create a thread with multiple messages on it.
    first_thread = add_fake_thread(db.session, default_namespace.id)
    add_fake_message(db.session, default_namespace.id, first_thread,
                     from_addr=[('', '*****@*****.**')],
                     received_date=datetime.datetime.utcnow(),
                     add_sent_category=True)
    add_fake_message(db.session, default_namespace.id, first_thread,
                     from_addr=[('', '*****@*****.**')],
                     received_date=datetime.datetime.utcnow(),
                     add_sent_category=True)

    # Now create another thread with the same participants
    older_date = datetime.datetime.utcnow() - datetime.timedelta(hours=1)
    second_thread = add_fake_thread(db.session, default_namespace.id)
    add_fake_message(db.session, default_namespace.id, second_thread,
                     from_addr=[('', '*****@*****.**')],
                     received_date=older_date,
                     add_sent_category=True)
    add_fake_message(db.session, default_namespace.id, second_thread,
                     from_addr=[('', '*****@*****.**')],
                     received_date=older_date,
                     add_sent_category=True)

    second_thread.recentdate = older_date
    db.session.commit()

    filtered_results = api_client.get_data('/[email protected]'
                                           '&limit=1&offset=0')
    assert len(filtered_results) == 1
    assert filtered_results[0]['id'] == first_thread.public_id

    filtered_results = api_client.get_data('/[email protected]'
                                           '&limit=1&offset=1')
    assert len(filtered_results) == 1
    assert filtered_results[0]['id'] == second_thread.public_id

    filtered_results = api_client.get_data('/[email protected]'
                                           '&limit=2&offset=0')
    assert len(filtered_results) == 2

    filtered_results = api_client.get_data('/[email protected]'
                                           '&limit=2&offset=1')
    assert len(filtered_results) == 1

    # Ensure that it works when using the _in filter
    filtered_results = api_client.get_data('/threads?in=sent'
                                           '&limit=2&offset=0')
    assert len(filtered_results) == 2

    filtered_results = api_client.get_data('/threads?in=sent'
                                           '&limit=1&offset=0')
    assert len(filtered_results) == 1
Example #36
0
def test_longpoll_delta_newitem(db, api_client,
                                default_namespace, thread):
    cursor = get_cursor(api_client, int(time.time() + 22),
                        default_namespace)
    url = url_concat('/delta/longpoll', {'cursor': cursor})
    start_time = time.time()
    # Spawn the request in background greenlet
    longpoll_greenlet = Greenlet.spawn(api_client.get_raw, url)
    # This should make it return immediately
    add_fake_message(db.session, default_namespace.id, thread,
                     from_addr=[('Bob', '*****@*****.**')])
    longpoll_greenlet.join()  # now block and wait
    end_time = time.time()
    assert end_time - start_time < LONGPOLL_EPSILON
    parsed_responses = json.loads(longpoll_greenlet.value.data)
    assert len(parsed_responses['deltas']) == 3
    assert set(k['object'] for k in parsed_responses['deltas']) == \
        set([u'message', u'contact', u'thread'])
Example #37
0
def test_ordering(api_client, db, default_namespace):
    for i in range(3):
        thr = add_fake_thread(db.session, default_namespace.id)
        received_date = (datetime.datetime.utcnow() +
                         datetime.timedelta(seconds=22 * (i + 1)))
        add_fake_message(db.session, default_namespace.id,
                         thr, received_date=received_date)
    ordered_results = api_client.get_data('/messages')
    ordered_dates = [result['date'] for result in ordered_results]
    assert ordered_dates == sorted(ordered_dates, reverse=True)

    ordered_results = api_client.get_data('/messages?limit=3')
    expected_public_ids = [
        public_id for public_id, in
        db.session.query(Message.public_id).
        filter(Message.namespace_id == default_namespace.id).
        order_by(desc(Message.received_date)).limit(3)]
    assert expected_public_ids == [r['id'] for r in ordered_results]
Example #38
0
def test_self_send(db, default_namespace):
    first_thread = add_fake_thread(db.session, default_namespace.id)
    first_thread.subject = 'Some kind of test'

    add_fake_message(db.session, default_namespace.id,
                     thread=first_thread,
                     subject='Some kind of test',
                     from_addr=[('Karim Hamidou', '*****@*****.**')],
                     to_addr=[('Karim Hamidou', '*****@*****.**')])

    msg2 = add_fake_message(db.session, default_namespace.id,
                            thread=None,
                            subject='Re: Some kind of test',
                            from_addr=[('Karim Hamidou', '*****@*****.**')],
                            to_addr=[('Karim Hamidou', '*****@*****.**')])

    matched_thread = fetch_corresponding_thread(db.session,
                                                default_namespace.id, msg2)
    assert matched_thread is first_thread, "Should match on self-send"
Example #39
0
def test_generic_grouping(db, default_account):
    thread = add_fake_thread(db.session, default_account.namespace.id)
    message = add_fake_message(db.session, default_account.namespace.id,
                               thread, subject="Golden Gate Park next Sat")
    folder = Folder(account=default_account, name='Inbox',
                    canonical_name='inbox')
    ImapUid(message=message, account_id=default_account.id,
            msg_uid=2222, folder=folder)

    thread = add_fake_thread(db.session, default_account.namespace.id)

    account = add_generic_imap_account(db.session)
    message = add_fake_message(db.session, account.namespace.id,
                               thread, subject="Golden Gate Park next Sat")

    thread = fetch_corresponding_thread(db.session,
                                        default_account.namespace.id, message)
    assert thread is None, ("fetch_similar_threads should "
                            "heed namespace boundaries")
Example #40
0
def test_threads_only_deleted_when_no_messages_left(db, default_account,
                                                    default_namespace,
                                                    marked_deleted_message,
                                                    thread, folder):
    handler = DeleteHandler(account_id=default_account.id,
                            namespace_id=default_namespace.id,
                            provider_name=default_account.provider,
                            uid_accessor=lambda m: m.imapuids,
                            message_ttl=0)
    # Add another message onto the thread
    add_fake_message(db.session, default_namespace.id, thread)

    handler.check(marked_deleted_message.deleted_at + timedelta(seconds=1))
    db.session.expire_all()
    # Check that the orphaned message was deleted.
    with pytest.raises(ObjectDeletedError):
        marked_deleted_message.id
    # Would raise ObjectDeletedError if thread was deleted.
    thread.id
def test_message_insert_creates_transaction(db, default_namespace):
    with db.session.no_autoflush:
        thr = add_fake_thread(db.session, default_namespace.id)
        msg = add_fake_message(db.session, default_namespace.id, thr)
        transaction = get_latest_transaction(db.session, "message", msg.id, default_namespace.id)
        assert transaction.command == "insert"

        # Test that the thread gets revised too
        transaction = get_latest_transaction(db.session, "thread", thr.id, default_namespace.id)
        assert transaction.command == "update"
Example #42
0
def test_self_send(db, default_namespace):
    first_thread = add_fake_thread(db.session, default_namespace.id)
    first_thread.subject = 'Some kind of test'

    add_fake_message(db.session, default_namespace.id,
                     thread=first_thread,
                     subject='Some kind of test',
                     from_addr=[('Karim Hamidou', '*****@*****.**')],
                     to_addr=[('Karim Hamidou', '*****@*****.**')])

    msg2 = add_fake_message(db.session, default_namespace.id,
                            thread=None,
                            subject='Re: Some kind of test',
                            from_addr=[('Karim Hamidou', '*****@*****.**')],
                            to_addr=[('Karim Hamidou', '*****@*****.**')])

    matched_thread = fetch_corresponding_thread(db.session,
                                                default_namespace.id, msg2)
    assert matched_thread is first_thread, "Should match on self-send"
Example #43
0
def test_namespace_delete_cascade(db, default_account):
    from inbox.models import Account, Thread, Message

    models = [Thread, Message]

    namespace = default_account.namespace
    namespace_id = namespace.id
    account_id = default_account.id

    account = db.session.query(Account).get(account_id)
    assert account

    thread = add_fake_thread(db.session, namespace_id)

    add_fake_message(db.session, namespace_id, thread)

    for m in models:
        c = db.session.query(m).filter(
            m.namespace_id == namespace_id).count()
        print "count for", m, ":", c
        assert c != 0

    fake_account = add_generic_imap_account(db.session)
    fake_account_id = fake_account.id

    assert fake_account_id != account.id and \
        fake_account.namespace.id != namespace_id

    thread = add_fake_thread(db.session, fake_account.namespace.id)

    add_fake_message(db.session, fake_account.namespace.id, thread)

    assert len(db.session.query(Namespace).filter(Namespace.id == namespace_id).all()) > 0

    # This test is separate from test_namespace_deletion because we want to
    # do a raw SQLAlchemy delete rather than using delete_namespace, which does
    # a bunch of extra work to ensure that objects associated with a Namespace
    # are actually deleted.
    db.session.query(Namespace).filter(Namespace.id == namespace_id).delete()
    db.session.commit()

    assert len(db.session.query(Namespace).filter(Namespace.id == namespace_id).all()) == 0
def test_message_updates_create_transaction(db, default_namespace):
    with db.session.no_autoflush:
        thr = add_fake_thread(db.session, default_namespace.id)
        msg = add_fake_message(db.session, default_namespace.id, thr)

        msg.is_read = True
        db.session.commit()
        transaction = get_latest_transaction(db.session, "message", msg.id, default_namespace.id)
        assert transaction.record_id == msg.id
        assert transaction.object_type == "message"
        assert transaction.command == "update"
Example #45
0
def test_reply_to_message_cascade(db, default_namespace, thread, message):
    reply = add_fake_message(db.session, default_namespace.id, thread)
    reply.reply_to_message = message
    db.session.commit()

    db.session.expire_all()
    db.session.delete(message)
    db.session.commit()

    assert db.session.query(Message).filter(Message.id == message.id).all() == []
    assert db.session.query(Message).filter(Message.id == reply.id).all() == [reply]
Example #46
0
def test_ordering(api_client, db, default_namespace):
    for i in range(3):
        thr = add_fake_thread(db.session, default_namespace.id)
        received_date = (datetime.datetime.utcnow() +
                         datetime.timedelta(seconds=22 * (i + 1)))
        add_fake_message(db.session,
                         default_namespace.id,
                         thr,
                         received_date=received_date)
    ordered_results = api_client.get_data('/messages')
    ordered_dates = [result['date'] for result in ordered_results]
    assert ordered_dates == sorted(ordered_dates, reverse=True)

    ordered_results = api_client.get_data('/messages?limit=3')
    expected_public_ids = [
        public_id for public_id, in db.session.query(Message.public_id).filter(
            Message.namespace_id == default_namespace.id).order_by(
                desc(Message.received_date)).limit(3)
    ]
    assert expected_public_ids == [r['id'] for r in ordered_results]
Example #47
0
def test_addresses_canonicalized(db, default_namespace, thread):
    msg = add_fake_message(db.session, default_namespace.id, thread,
                           from_addr=[('', '*****@*****.**')],
                           cc_addr=[('', '*****@*****.**')],
                           bcc_addr=[('', '*****@*****.**')])

    # Because Gmail addresses with and without periods are the same, check that
    # there are three MessageContactAssociation instances attached to the
    # message (one each from the from/to/cc fields), but that they reference
    # the same contact.
    assert len(msg.contacts) == 3
    assert len(set(association.contact for association in msg.contacts)) == 1
Example #48
0
def test_message_updates_create_transaction(db, default_namespace):
    with db.session.no_autoflush:
        thr = add_fake_thread(db.session, default_namespace.id)
        msg = add_fake_message(db.session, default_namespace.id, thr)

        msg.is_read = True
        db.session.commit()
        transaction = get_latest_transaction(db.session, 'message', msg.id,
                                             default_namespace.id)
        assert transaction.record_id == msg.id
        assert transaction.object_type == 'message'
        assert transaction.command == 'update'
Example #49
0
def test_message_insert_creates_transaction(db, default_namespace):
    with db.session.no_autoflush:
        thr = add_fake_thread(db.session, default_namespace.id)
        msg = add_fake_message(db.session, default_namespace.id, thr)
        transaction = get_latest_transaction(db.session, 'message', msg.id,
                                             default_namespace.id)
        assert transaction.command == 'insert'

        # Test that the thread gets revised too
        transaction = get_latest_transaction(db.session, 'thread', thr.id,
                                             default_namespace.id)
        assert transaction.command == 'update'
def test_object_type_distinguishes_messages_and_drafts(db, default_namespace):
    with db.session.no_autoflush:
        thr = add_fake_thread(db.session, default_namespace.id)
        msg = add_fake_message(db.session, default_namespace.id, thr)
        msg.is_draft = 1
        db.session.commit()
        transaction = get_latest_transaction(db.session, "draft", msg.id, default_namespace.id)
        assert transaction.command == "update"
        db.session.delete(msg)
        db.session.commit()
        transaction = get_latest_transaction(db.session, "draft", msg.id, default_namespace.id)
        assert transaction.command == "delete"
Example #51
0
def test_thread_received_recent_date(db, api_client, default_account):
    date1 = datetime.datetime(2015, 1, 1, 0, 0, 0)
    date2 = datetime.datetime(2012, 1, 1, 0, 0, 0)

    thread1 = add_fake_thread(db.session, default_account.namespace.id)

    date_dict = dict()

    add_fake_message(db.session, default_account.namespace.id, thread1,
                     subject="Test Thread 1", received_date=date1,
                     add_sent_category=True)
    add_fake_message(db.session, default_account.namespace.id, thread1,
                     subject="Test Thread 1", received_date=date2)

    date_dict["Test Thread 1"] = date2

    thread2 = add_fake_thread(db.session, default_account.namespace.id)
    add_fake_message(db.session, default_account.namespace.id, thread2,
                     subject="Test Thread 2", received_date=date1,
                     add_sent_category=True)

    date_dict["Test Thread 2"] = date1

    resp = api_client.get_raw('/threads/')
    assert resp.status_code == 200
    threads = json.loads(resp.data)

    for thread in threads:
        assert date_dict[thread['subject']] == \
            datetime.datetime.fromtimestamp(
                thread['last_message_received_timestamp'])
def test_generic_drafts_flag_constrained_by_folder(db, generic_account,
                                                   folder_role):
    msg_uid = 22
    thread = add_fake_thread(db.session, generic_account.namespace.id)
    message = add_fake_message(db.session, generic_account.namespace.id,
                               thread)
    folder = add_fake_folder(db.session, generic_account)
    add_fake_imapuid(db.session, generic_account.id, message, folder, msg_uid)

    new_flags = {msg_uid: Flags(('\\Draft', ), None)}
    update_metadata(generic_account.id, folder.id, folder_role, new_flags,
                    db.session)
    assert message.is_draft == (folder_role == 'drafts')
Example #53
0
def test_updating_message_categories_increments_version(
        db, thread, default_namespace):
    assert thread.version == 0

    message = add_fake_message(db.session, default_namespace.id, thread)
    category = add_fake_category(db.session, default_namespace.id,
                                 'mia kategorio')

    # Modifying message's categories increments the thread.version
    message.categories = [category]
    db.session.commit()

    assert thread.version == 2
Example #54
0
def test_exclude_account(api_client, db, default_namespace, thread):
    ts = int(time.time() + 22)
    cursor = get_cursor(api_client, ts)

    # Create `account`, `message`, `thread` deltas
    default_namespace.account.sync_state = 'invalid'
    db.session.commit()
    add_fake_message(db.session, default_namespace.id, thread)

    # Verify the default value of `exclude_account`=True and
    # the account delta is *not* included
    sync_data = api_client.get_data('/delta?cursor={}'.format(cursor))
    assert len(sync_data['deltas']) == 2
    assert set([d['object'] for d in sync_data['deltas']]) == \
        set(['message', 'thread'])

    # Verify setting `exclude_account`=True returns the account delta as well.
    sync_data = api_client.get_data('/delta?cursor={}&exclude_account=false'.
                                    format(cursor))
    assert len(sync_data['deltas']) == 3
    assert set([d['object'] for d in sync_data['deltas']]) == \
        set(['message', 'thread', 'account'])
Example #55
0
def test_object_type_distinguishes_messages_and_drafts(db, default_namespace):
    with db.session.no_autoflush:
        thr = add_fake_thread(db.session, default_namespace.id)
        msg = add_fake_message(db.session, default_namespace.id, thr)
        msg.is_draft = 1
        db.session.commit()
        transaction = get_latest_transaction(db.session, 'draft', msg.id,
                                             default_namespace.id)
        assert transaction.command == 'update'
        db.session.delete(msg)
        db.session.commit()
        transaction = get_latest_transaction(db.session, 'draft', msg.id,
                                             default_namespace.id)
        assert transaction.command == 'delete'