예제 #1
0
def test_contacts_updated(api_client):
    """Tests that draft-contact associations are properly created and
    updated."""
    draft = {
        'to': [{'email': '*****@*****.**'}, {'email': '*****@*****.**'}]
    }

    r = api_client.post_data('/drafts', draft)
    assert r.status_code == 200
    draft_id = json.loads(r.data)['id']
    draft_version = json.loads(r.data)['version']

    r = api_client.get_data('/[email protected]')
    assert len(r) == 1

    updated_draft = {
        'to': [{'email': '*****@*****.**'}, {'email': '*****@*****.**'}],
        'version': draft_version
    }

    r = api_client.put_data('/drafts/{}'.format(draft_id), updated_draft)
    assert r.status_code == 200

    r = api_client.get_data('/[email protected]')
    assert len(r) == 1

    r = api_client.get_data('/[email protected]')
    assert len(r) == 0

    r = api_client.get_data('/[email protected]')
    assert len(r) == 1
def test_api_expand_recurring_message(db, api_client, message,
                                      recurring_event):
    # This is a regression test for https://phab.nylas.com/T3556
    # ("InflatedEvent should not be committed" exception in API").
    event = recurring_event
    event.message = message
    db.session.commit()

    events = api_client.get_data('/events?expand_recurring=false')
    assert len(events) == 1

    # Make sure the recurrence info is on the recurring event
    for e in events:
        if e['title'] == 'recurring-weekly':
            assert e.get('recurrence') is not None
            assert e.get('message_id') is not None

    r = api_client.get_raw('/events?expand_recurring=true')
    assert r.status_code == 200

    all_events = api_client.get_data('/events?expand_recurring=true')
    assert len(all_events) != 0

    for event in all_events:
        assert event['master_event_id'] is not None
        assert 'message_id' not in event
예제 #3
0
def test_account(db, api_client, generic_account, gmail_account):
    # Because we're using the generic_account namespace
    api_client = new_api_client(db, generic_account.namespace)

    resp_data = api_client.get_data('/account')

    assert resp_data['id'] == generic_account.namespace.public_id
    assert resp_data['object'] == 'account'
    assert resp_data['account_id'] == generic_account.namespace.public_id
    assert resp_data['email_address'] == generic_account.email_address
    assert resp_data['name'] == generic_account.name
    assert resp_data['organization_unit'] == 'folder'
    assert 'sync_state' in resp_data
    assert 'server_settings' not in resp_data

    # Because we're using the gmail account namespace
    api_client = new_api_client(db, gmail_account.namespace)

    resp_data = api_client.get_data('/account')

    assert resp_data['id'] == gmail_account.namespace.public_id
    assert resp_data['provider'] == 'gmail'
    assert resp_data['organization_unit'] == 'label'
    assert 'sync_state' in resp_data
    assert 'server_settings' not in resp_data
예제 #4
0
def test_api_get(contacts_provider, contact_sync, db, api_client,
                 default_namespace):
    contacts_provider.supply_contact('Contact One',
                                     '*****@*****.**')
    contacts_provider.supply_contact('Contact Two',
                                     '*****@*****.**')

    contact_sync.provider = contacts_provider
    contact_sync.sync()

    contact_list = api_client.get_data('/contacts')

    contact_ids = [contact['id'] for contact in contact_list]

    c1found = False
    c2found = False
    for c_id in contact_ids:
        contact = api_client.get_data('/contacts/' + c_id)

        if contact['name'] == 'Contact One':
            c1found = True

        if contact['name'] == 'Contact Two':
            c2found = True

    assert c1found
    assert c2found
예제 #5
0
def test_events_are_condensed(api_client, message):
    """
    Test that multiple revisions of the same object are rolled up in the
    delta response.

    """
    ts = int(time.time() + 22)
    cursor = get_cursor(api_client, ts)

    # Modify a message, then modify it again
    message_id = api_client.get_data('/messages/')[0]['id']
    message_path = '/messages/{}'.format(message_id)
    api_client.put_data(message_path, {'unread': True})
    api_client.put_data(message_path, {'unread': False})
    api_client.put_data(message_path, {'unread': True})

    # Check that successive modifies are condensed.
    sync_data = api_client.get_data('/delta?cursor={}'.format(cursor))
    deltas = sync_data['deltas']
    # A message modify propagates to its thread
    message_deltas = [d for d in deltas if d['object'] == 'message']
    assert len(message_deltas) == 1

    delta = message_deltas[0]
    assert delta['object'] == 'message' and delta['event'] == 'modify'
    assert delta['attributes']['unread'] is True
예제 #6
0
def test_account_expanded(db, api_client, generic_account, gmail_account):
    # Generic accounts expose a `server_settings` attribute
    # Custom IMAP
    api_client = new_api_client(db, generic_account.namespace)
    resp_data = api_client.get_data('/account/?view=expanded')
    assert resp_data['provider'] == 'custom'
    assert 'server_settings' in resp_data
    assert set(resp_data['server_settings']) == set({
        'imap_host': 'imap.custom.com',
        'smtp_host': 'smtp.custom.com',
        'imap_port': 993,
        'smtp_port': 587,
        'ssl_required': True})

    # Yahoo
    yahoo_account = add_fake_yahoo_account(db.session)
    api_client = new_api_client(db, yahoo_account.namespace)
    resp_data = api_client.get_data('/account/?view=expanded')
    assert resp_data['provider'] == 'yahoo'
    assert 'server_settings' in resp_data
    assert set(resp_data['server_settings']) == set({
        'imap_host': 'imap.mail.yahoo.com',
        'smtp_host': 'smtp.mail.yahoo.com',
        'imap_port': 993,
        'smtp_port': 587,
        'ssl_required': True})

    # Gmail accounts don't expose a `server_settings` attribute
    api_client = new_api_client(db, gmail_account.namespace)
    resp_data = api_client.get_data('/account/?view=expanded')
    assert resp_data['provider'] == 'gmail'
    assert 'server_settings' not in resp_data
예제 #7
0
def test_api_get(db, api_client, calendar):
    e_data = {'title': 'subj', 'when': {'time': 1},
              'calendar_id': calendar.public_id, 'location': 'InboxHQ'}
    e_data2 = {'title': 'subj2', 'when': {'time': 1},
               'calendar_id': calendar.public_id, 'location': 'InboxHQ'}
    api_client.post_data('/events', e_data)
    api_client.post_data('/events', e_data2)

    event_list = api_client.get_data('/events')

    event_ids = [event['id'] for event in event_list]

    c1found = False
    c2found = False
    for c_id in event_ids:
        event = api_client.get_data('/events/' + c_id)

        if event['title'] == 'subj':
            c1found = True

        if event['title'] == 'subj2':
            c2found = True

    assert c1found
    assert c2found
예제 #8
0
def test_delete_from_readonly_calendar(db, default_namespace, api_client):

    add_fake_event(db.session, default_namespace.id,
                   calendar=db.session.query(Calendar).filter(
                       Calendar.namespace_id == default_namespace.id,
                       Calendar.read_only == True).first(),  # noqa
                   read_only=True)
    calendar_list = api_client.get_data('/calendars')

    read_only_calendar = None
    for c in calendar_list:
        if c['read_only']:
            read_only_calendar = c
            break
    events = api_client.get_data('/events?calendar_id={}'.format(
        read_only_calendar['id']))
    for event in events:
        if event['read_only']:
            read_only_event = event
            break

    assert read_only_calendar
    assert read_only_event
    e_id = read_only_event['id']
    resp = api_client.delete('/events/{}'.format(e_id))
    assert resp.status_code == 400
예제 #9
0
def test_update_draft(api_client):
    with freeze_time(datetime.now()) as freezer:
        original_draft = {"subject": "original draft", "body": "parent draft"}
        r = api_client.post_data("/drafts", original_draft)
        draft_public_id = json.loads(r.data)["id"]
        version = json.loads(r.data)["version"]
        assert version == 0

        freezer.tick()

        updated_draft = {"subject": "updated draft", "body": "updated draft", "version": version}

        r = api_client.put_data("/drafts/{}".format(draft_public_id), updated_draft)
        updated_public_id = json.loads(r.data)["id"]
        updated_version = json.loads(r.data)["version"]

        assert updated_public_id == draft_public_id
        assert updated_version > 0

        drafts = api_client.get_data("/drafts")
        assert len(drafts) == 1
        assert drafts[0]["id"] == updated_public_id

        # Check that the thread is updated too.
        thread = api_client.get_data("/threads/{}".format(drafts[0]["thread_id"]))
        assert thread["subject"] == "updated draft"
        assert thread["first_message_timestamp"] == drafts[0]["date"]
        assert thread["last_message_timestamp"] == drafts[0]["date"]
예제 #10
0
def test_create_draft_with_attachments(api_client, attachments, example_draft):
    attachment_ids = []
    upload_path = '/files'
    for filename, path in attachments:
        data = {'file': (open(path, 'rb'), filename)}
        r = api_client.post_raw(upload_path, data=data)
        assert r.status_code == 200
        attachment_id = json.loads(r.data)[0]['id']
        attachment_ids.append(attachment_id)

    first_attachment = attachment_ids.pop()

    example_draft['file_ids'] = [first_attachment]
    r = api_client.post_data('/drafts', example_draft)
    assert r.status_code == 200
    returned_draft = json.loads(r.data)
    draft_public_id = returned_draft['id']
    assert returned_draft['version'] == 0
    example_draft['version'] = returned_draft['version']
    assert len(returned_draft['files']) == 1

    attachment_ids.append(first_attachment)
    example_draft['file_ids'] = attachment_ids
    r = api_client.put_data('/drafts/{}'.format(draft_public_id),
                            example_draft)
    assert r.status_code == 200
    returned_draft = json.loads(r.data)
    assert len(returned_draft['files']) == 3
    assert returned_draft['version'] == 1
    example_draft['version'] = returned_draft['version']

    # Make sure we can't delete the files now
    for file_id in attachment_ids:
        r = api_client.delete('/files/{}'.format(file_id))
        assert r.status_code == 400

    # Now remove the attachment
    example_draft['file_ids'] = [first_attachment]
    r = api_client.put_data('/drafts/{}'.format(draft_public_id),
                            example_draft)

    draft_data = api_client.get_data('/drafts/{}'.format(draft_public_id))
    assert len(draft_data['files']) == 1
    assert draft_data['version'] == 2
    example_draft['version'] = draft_data['version']

    example_draft['file_ids'] = []
    r = api_client.put_data('/drafts/{}'.format(draft_public_id),
                            example_draft)
    draft_data = api_client.get_data('/drafts/{}'.format(draft_public_id))
    assert r.status_code == 200
    assert len(draft_data['files']) == 0
    assert draft_data['version'] == 3

    # now that they're not attached, we should be able to delete them
    for file_id in attachment_ids:
        r = api_client.delete('/files/{}'.format(file_id))
        assert r.status_code == 200
예제 #11
0
def test_get_with_id(api_client, uploaded_file_ids, filename):
    # See comment in uploaded_file_ids()
    if filename == 'piece-jointe.jpg':
        filename = u'pièce-jointe.jpg'
    elif filename == 'andra-moi-ennepe.txt':
        filename = u'ἄνδρα μοι ἔννεπε'
    in_file = api_client.get_data(u'/files?filename={}'.format(filename))[0]
    data = api_client.get_data('/files/{}'.format(in_file['id']))
    assert data['filename'] == filename
예제 #12
0
def test_gmail_pagination(db, default_account,
                          patch_crispin_client,
                          patch_handler_from_provider,
                          folder):
    for i in range(10):
        thread = add_fake_thread(db.session, default_account.namespace.id)
        message = add_fake_message(db.session, default_account.namespace.id,
                                   thread=thread,
                                   from_addr=[{'name': '', 'email':
                                               '{}@test.com'.format(str(i))}],
                                   subject='hi',
                                   g_msgid=i,
                                   received_date=datetime.
                                   datetime(2000 + i, 1, 1, 1, 0, 0))

        add_fake_imapuid(db.session, default_account.id, message,
                         folder, i)

    first_ten_messages_db = db.session.query(Message)\
                            .filter(Message.namespace_id ==
                                    default_account.namespace.id). \
                            order_by(desc(Message.received_date)). \
                            limit(10).all()

    api_client = new_api_client(db, default_account.namespace)

    first_ten_messages_api = api_client.get_data('/messages/search?q=hi'
                                                      '&limit=10')
    assert len(first_ten_messages_api) == len(first_ten_messages_db)

    for db_message, api_message in zip(first_ten_messages_db,
                                        first_ten_messages_api):
        assert db_message.public_id == api_message['id']

    imap_uids = db.session.query(ImapUid).join(Message) \
                    .filter(
                        ImapUid.message_id == Message.id,
                        Message.g_msgid != None).all()
    uids = [uid.msg_uid for uid in imap_uids]

    first_ten_threads_db = db.session.query(Thread) \
                            .join(Message) \
                            .join(ImapUid) \
                            .filter(ImapUid.account_id == default_account.id,
                                    ImapUid.msg_uid.in_(uids),
                                    Thread.id == Message.thread_id)\
                            .order_by(desc(Message.received_date)) \
                            .limit(10).all()

    first_ten_threads_api = api_client.get_data('/threads/search?q=hi'
                                                      '&limit=10')

    assert len(first_ten_threads_api) == len(first_ten_threads_db)

    for db_thread, api_thread in zip(first_ten_threads_db,
                                        first_ten_threads_api):
        assert db_thread.public_id == api_thread['id']
예제 #13
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
예제 #14
0
def test_gmail_message_search(api_client, default_account,
                              patch_token_manager,
                              patch_gmail_search_response,
                              sorted_gmail_messages, is_streaming):
    search_client = get_search_client(default_account)
    assert isinstance(search_client, GmailSearchClient)

    if is_streaming:
        messages = api_client.get_data('/messages/search/streaming?q=blah%20blah%20blah')
    else:
        messages = api_client.get_data('/messages/search?q=blah%20blah%20blah')

    assert_search_result(sorted_gmail_messages, messages)
예제 #15
0
def test_get_invalid(api_client, uploaded_file_ids):
    data = api_client.get_data('/files/0000000000000000000000000')
    assert data['message'].startswith("Couldn't find file")
    data = api_client.get_data('/files/!')
    assert data['message'].startswith("Invalid id")

    data = api_client.get_data('/files/0000000000000000000000000/download')
    assert data['message'].startswith("Couldn't find file")
    data = api_client.get_data('/files/!/download')
    assert data['message'].startswith("Invalid id")

    r = api_client.delete('/files/0000000000000000000000000')
    assert r.status_code == 404
    r = api_client.delete('/files/!')
    assert r.status_code == 400
예제 #16
0
def test_gmail_search_unicode(db, api_client, test_gmail_thread,
                              patch_token_manager,
                              patch_gmail_search_response,
                              default_account,
                              sorted_gmail_messages,
                              sorted_gmail_threads, is_streaming):
    search_client = get_search_client(default_account)
    assert isinstance(search_client, GmailSearchClient)

    if is_streaming:
        threads = api_client.get_data('/threads/search/streaming?q=存档')
    else:
        threads = api_client.get_data('/threads/search?q=存档')

    assert_search_result(sorted_gmail_threads, threads)
예제 #17
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'] == []
예제 #18
0
def test_resource_views(resource_name, db, api_client,
                        message, thread, event, folder, label, contact):
    """Exercises various tests for views, mostly related to
    filtering. Note: this only tests views, it assumes the
    resources are working as expected."""
    elements = api_client.get_data('/{}'.format(resource_name))
    count = api_client.get_data('/{}?view=count'.format(resource_name))

    assert count["count"] == len(elements)

    ids = api_client.get_data('/{}?view=ids'.format(resource_name))

    for i, elem in enumerate(elements):
        assert isinstance(ids[i], basestring), \
            "&views=ids should return string"
        assert elem["id"] == ids[i], "view=ids should preserve order"
def test_api_create(db, api_client, calendar):
    e_data = {
        'title': 'Friday Office Party',
        'when': {'time': 1407542195},
        'calendar_id': calendar.public_id,
        'participants': [{
            'name': 'alyssa p. hacker',
            'email': '*****@*****.**'
        }]
    }

    e_resp = api_client.post_data('/events', e_data)
    e_resp_data = json.loads(e_resp.data)

    assert len(e_resp_data['participants']) == 1
    participant = e_resp_data['participants'][0]
    assert participant['name'] == e_data['participants'][0]['name']
    assert participant['email'] == e_data['participants'][0]['email']
    assert participant['status'] == 'noreply'

    e_resp_data = api_client.get_data('/events/' + e_resp_data['id'])

    assert len(e_resp_data['participants']) == 1
    participant = e_resp_data['participants'][0]
    assert participant['name'] == e_data['participants'][0]['name']
    assert participant['email'] == e_data['participants'][0]['email']
    assert participant['status'] == 'noreply'
def test_api_override_serialization(db, api_client, default_namespace,
                                    recurring_event):
    event = recurring_event

    override = Event(original_start_time=event.start,
                     master_event_uid=event.uid,
                     namespace_id=default_namespace.id,
                     calendar_id=event.calendar_id)
    override.update(event)
    override.uid = event.uid + "_" + event.start.strftime("%Y%m%dT%H%M%SZ")
    override.master = event
    override.master_event_uid = event.uid
    override.cancelled = True
    db.session.add(override)
    db.session.commit()

    filter = 'starts_after={}&ends_before={}'.format(
        urlsafe(event.start.replace(hours=-1)),
        urlsafe(event.start.replace(weeks=+1)))
    events = api_client.get_data('/events?' + filter)
    # We should have the base event and the override back, but no extras;
    # this allows clients to do their own expansion, should they ever desire
    # to experience the joy that is RFC 2445 section 4.8.5.4.
    assert len(events) == 2
    assert events[0].get('object') == 'event'
    assert events[0].get('recurrence') is not None
    assert events[1].get('object') == 'event'
    assert events[1].get('status') == 'cancelled'
예제 #21
0
def test_create_draft_replying_to_message(api_client, message):
    message = api_client.get_data("/messages")[0]
    reply_draft = {"subject": "test reply", "body": "test reply", "reply_to_message_id": message["id"]}
    r = api_client.post_data("/drafts", reply_draft)
    data = json.loads(r.data)
    assert data["reply_to_message_id"] == message["id"]
    assert data["thread_id"] == message["thread_id"]
예제 #22
0
def test_update_to_nonexistent_draft(api_client):
    updated_draft = {"subject": "updated draft", "body": "updated draft", "version": 22}

    r = api_client.put_data("/drafts/{}".format("notarealid"), updated_draft)
    assert r.status_code == 404
    drafts = api_client.get_data("/drafts")
    assert len(drafts) == 0
예제 #23
0
def test_drafts_filter(api_client, example_draft):
    r = api_client.post_data("/drafts", example_draft)
    thread_id = json.loads(r.data)["thread_id"]

    reply_draft = {"subject": "test reply", "body": "test reply", "thread_id": thread_id}
    r = api_client.post_data("/drafts", reply_draft)

    _filter = "?thread_id=0000000000000000000000000"
    results = api_client.get_data("/drafts" + _filter)
    assert len(results) == 0

    results = api_client.get_data("/drafts?thread_id={}".format(thread_id))
    assert len(results) == 2

    results = api_client.get_data("/drafts?offset={}&thread_id={}".format(1, thread_id))
    assert len(results) == 1
예제 #24
0
def test_query_target(db, api_client, thread, default_namespace):
    cat = Category(namespace_id=default_namespace.id,
                   name='inbox', display_name='Inbox', type_='label')
    for _ in range(3):
        message = add_fake_message(db.session, default_namespace.id, thread,
                                   to_addr=[('Bob', '*****@*****.**')],
                                   from_addr=[('Alice', '*****@*****.**')],
                                   subject='some subject')
        message.categories.add(cat)
    db.session.commit()

    results = api_client.get_data('/messages?in=inbox')
    assert len(results) == 3

    count = api_client.get_data('/messages?in=inbox&view=count')
    assert count['count'] == 3
예제 #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
예제 #26
0
def test_api_list(db, api_client, calendar):
    e_data = {'title': 'subj', 'description': 'body1',
              'calendar_id': calendar.public_id,
              'when': {'time': 1}, 'location': 'InboxHQ'}
    e_data2 = {'title': 'subj2', 'description': 'body2',
               'calendar_id': calendar.public_id,
               'when': {'time': 1}, 'location': 'InboxHQ'}
    api_client.post_data('/events', e_data)
    api_client.post_data('/events', e_data2)

    event_list = api_client.get_data('/events')
    event_titles = [event['title'] for event in event_list]
    assert 'subj' in event_titles
    assert 'subj2' in event_titles

    event_descriptions = [event['description'] for event in event_list]
    assert 'body1' in event_descriptions
    assert 'body2' in event_descriptions

    event_ids = [event['id'] for event in event_list]

    for e_id in event_ids:
        ev = db.session.query(Event).filter_by(public_id=e_id).one()
        db.session.delete(ev)
    db.session.commit()
예제 #27
0
def test_adding_a_mutually_exclusive_label_replaces_the_other(
        db, api_client, default_account, folder_and_message_maps, label):
    # Verify a Gmail message can only have ONE of the 'all', 'trash', 'spam'
    # labels at a time. We specifically test that adding 'all'/ 'trash'/ 'spam'
    # to a message in one of the other two folders *replaces*
    # the existing label with the label being added.
    folder_map, message_map = folder_and_message_maps
    label_to_add = folder_map[label]

    for key in message_map:
        if key == label:
            continue

        message = message_map[key]
        resp_data = api_client.get_data('/messages/{}'.format(message.public_id))
        labels = resp_data['labels']
        assert len(labels) == 1
        assert labels[0]['name'] == key
        existing_label = labels[0]['id']

        # Adding 'all'/ 'trash'/ 'spam' removes the existing one,
        # irrespective of whether it's provided in the request or not.
        response = api_client.put_data(
            '/messages/{}'.format(message.public_id),
            {'label_ids': [label_to_add.category.public_id,
                           existing_label]})
        labels = json.loads(response.data)['labels']
        assert len(labels) == 1
        assert labels[0]['name'] == label
예제 #28
0
def test_conflicting_updates(api_client):
    original_draft = {
        'subject': 'parent draft',
        'body': 'parent draft'
    }
    r = api_client.post_data('/drafts', original_draft)
    original_public_id = json.loads(r.data)['id']
    version = json.loads(r.data)['version']

    updated_draft = {
        'subject': 'updated draft',
        'body': 'updated draft',
        'version': version
    }
    r = api_client.put_data('/drafts/{}'.format(original_public_id),
                            updated_draft)
    assert r.status_code == 200
    updated_public_id = json.loads(r.data)['id']
    updated_version = json.loads(r.data)['version']
    assert updated_version != version

    conflicting_draft = {
        'subject': 'conflicting draft',
        'body': 'conflicting draft',
        'version': version
    }
    r = api_client.put_data('/drafts/{}'.format(original_public_id),
                            conflicting_draft)
    assert r.status_code == 409

    drafts = api_client.get_data('/drafts')
    assert len(drafts) == 1
    assert drafts[0]['id'] == updated_public_id
예제 #29
0
def test_adding_a_mutually_exclusive_label_does_not_affect_custom_labels(
        db, api_client, default_account, folder_and_message_maps, label):
    folder_map, message_map = folder_and_message_maps
    label_to_add = folder_map[label]

    for key in message_map:
        if key == label:
            continue

        message = message_map[key]
        add_custom_label(db, default_account, message)
        resp_data = api_client.get_data('/messages/{}'.format(message.public_id))
        labels = resp_data['labels']
        assert len(labels) == 2
        assert key in [l['name'] for l in labels]
        assert '<3' in [l['display_name'] for l in labels]

        # Adding only 'all'/ 'trash'/ 'spam' does not change custom labels.
        response = api_client.put_data(
            '/messages/{}'.format(message.public_id),
            {'label_ids': [label_to_add.category.public_id] +
                [l['id'] for l in labels]})
        labels = json.loads(response.data)['labels']
        assert len(labels) == 2
        assert label in [l['name'] for l in labels]
        assert '<3' in [l['display_name'] for l in labels]
예제 #30
0
def test_adding_inbox_adds_all_and_removes_trash_spam(
        db, api_client, default_account, folder_and_message_maps, label):
    # Verify a Gmail message in 'trash', 'spam' cannot have 'inbox'.
    # This time we test that adding 'inbox' to a message in the 'trash'/ 'spam'
    # moves it to 'all' in addition to adding 'inbox'.
    folder_map, message_map = folder_and_message_maps

    message = message_map[label]
    resp_data = api_client.get_data('/messages/{}'.format(message.public_id))
    labels = resp_data['labels']
    assert len(labels) == 1
    assert labels[0]['name'] == label
    existing_label = labels[0]['id']

    inbox_label = add_fake_label(db.session, default_account, 'Inbox', 'inbox')
    db.session.commit()

    # Adding 'inbox' adds 'all', replacing 'trash'/ 'spam' if needed.
    response = api_client.put_data(
        '/messages/{}'.format(message.public_id),
        {'label_ids': [inbox_label.category.public_id, existing_label]})
    db.session.commit()
    labels = json.loads(response.data)['labels']
    assert len(labels) == 2
    assert set([l['name'] for l in labels]) == set(['all', 'inbox'])
예제 #31
0
def test_account(db, api_client, generic_account, gmail_account):

    # Because we're using the generic_account namespace
    api_client = new_api_client(db, generic_account.namespace)

    resp_data = api_client.get_data('/account')

    assert resp_data['id'] == generic_account.namespace.public_id
    assert resp_data['object'] == 'account'
    assert resp_data['account_id'] == generic_account.namespace.public_id
    assert resp_data['email_address'] == generic_account.email_address
    assert resp_data['name'] == generic_account.name
    assert resp_data['organization_unit'] == 'folder'

    # Because we're using the gmail account namespace
    api_client = new_api_client(db, gmail_account.namespace)

    resp_data = api_client.get_data('/account')

    assert resp_data['id'] == gmail_account.namespace.public_id
    assert resp_data['provider'] == 'gmail'
    assert resp_data['organization_unit'] == 'label'
예제 #32
0
def test_message_labels(db, gmail_account):
    # Because we're using the gmail_account namespace
    api_client = new_api_client(db, gmail_account.namespace)

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

    resp_data = api_client.get_data('/threads/{}'.format(
        gmail_thread.public_id))

    assert resp_data['id'] == gmail_thread.public_id
    assert resp_data['object'] == 'thread'
    assert 'labels' in resp_data and 'folders' not in resp_data

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

    assert resp_data['id'] == gmail_message.public_id
    assert resp_data['object'] == 'message'
    assert 'labels' in resp_data and 'folders' not in resp_data
예제 #33
0
def test_api_list(contacts_provider, contact_sync, db, api_client,
                  default_namespace):
    contacts_provider.supply_contact('Contact One',
                                     '*****@*****.**')
    contacts_provider.supply_contact('Contact Two',
                                     '*****@*****.**')

    contact_sync.provider = contacts_provider
    contact_sync.sync()

    contact_list = api_client.get_data('/contacts')
    contact_names = [contact['name'] for contact in contact_list]
    assert 'Contact One' in contact_names
    assert 'Contact Two' in contact_names

    contact_emails = [contact['email'] for contact in contact_list]
    assert '*****@*****.**' in contact_emails
    assert '*****@*****.**' in contact_emails

    contact_count = api_client.get_data('/contacts?view=count')
    assert contact_count['count'] == db.session.query(Contact). \
        filter(Contact.namespace_id == default_namespace.id).count()
예제 #34
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'])
예제 #35
0
def test_account_delta(api_client, db, default_namespace):
    ts = int(time.time() + 22)
    cursor = get_cursor(api_client, ts)

    account = default_namespace.account

    # Create an `account` delta
    default_namespace.account.sync_state = 'invalid'
    db.session.commit()

    sync_data = api_client.get_data('/delta?cursor={}&exclude_account=false'.
                                    format(cursor))
    assert len(sync_data['deltas']) == 1
    delta = sync_data['deltas'][0]
    assert delta['object'] == 'account'
    assert delta['event'] == 'modify'
    assert delta['attributes']['id'] == default_namespace.public_id
    assert delta['attributes']['account_id'] == default_namespace.public_id
    assert delta['attributes']['email_address'] == account.email_address
    assert delta['attributes']['name'] == account.name
    assert delta['attributes']['provider'] == account.provider
    assert delta['attributes']['organization_unit'] == account.category_type
    assert delta['attributes']['sync_state'] == 'invalid'

    cursor = sync_data['cursor_end']

    # Create an new `account` delta
    default_namespace.account.sync_state = 'running'
    db.session.commit()
    sync_data = api_client.get_data('/delta?cursor={}&exclude_account=false'.
                                    format(cursor))

    assert len(sync_data['deltas']) == 1
    delta = sync_data['deltas'][0]
    assert delta['object'] == 'account'
    assert delta['event'] == 'modify'
    assert delta['attributes']['id'] == default_namespace.public_id
    assert delta['attributes']['sync_state'] == 'running'
예제 #36
0
def test_account_delta(api_client, db, default_namespace):
    ts = int(time.time() + 22)
    cursor = get_cursor(api_client, ts)

    account = default_namespace.account

    # Create an `account` delta
    default_namespace.account.sync_state = "invalid"
    db.session.commit()

    sync_data = api_client.get_data(
        "/delta?cursor={}&exclude_account=false".format(cursor))
    assert len(sync_data["deltas"]) == 1
    delta = sync_data["deltas"][0]
    assert delta["object"] == "account"
    assert delta["event"] == "modify"
    assert delta["attributes"]["id"] == default_namespace.public_id
    assert delta["attributes"]["account_id"] == default_namespace.public_id
    assert delta["attributes"]["email_address"] == account.email_address
    assert delta["attributes"]["name"] == account.name
    assert delta["attributes"]["provider"] == account.provider
    assert delta["attributes"]["organization_unit"] == account.category_type
    assert delta["attributes"]["sync_state"] == "invalid"

    cursor = sync_data["cursor_end"]

    # Create an new `account` delta
    default_namespace.account.sync_state = "running"
    db.session.commit()
    sync_data = api_client.get_data(
        "/delta?cursor={}&exclude_account=false".format(cursor))

    assert len(sync_data["deltas"]) == 1
    delta = sync_data["deltas"][0]
    assert delta["object"] == "account"
    assert delta["event"] == "modify"
    assert delta["attributes"]["id"] == default_namespace.public_id
    assert delta["attributes"]["sync_state"] == "running"
예제 #37
0
def test_gmail_search_unicode(db, api_client, test_gmail_thread,
                              default_account,
                              patch_crispin_client,
                              patch_handler_from_provider,
                              sorted_gmail_threads):
    Folder.find_or_create(db.session, default_account,
                          '存档', '存档')
    search_client = get_search_client(default_account)
    assert search_client.__class__.__name__ == 'GmailSearchClient'

    threads = api_client.get_data('/threads/search?q=存档')

    for sorted_thread, result_thread in zip(sorted_gmail_threads, threads):
        assert sorted_thread.public_id == result_thread['id']
예제 #38
0
def test_send_existing_draft(patch_smtp, api_client, example_draft):
    r = api_client.post_data("/drafts", example_draft)
    draft_public_id = json.loads(r.data)["id"]
    version = json.loads(r.data)["version"]

    r = api_client.post_data("/send", {
        "draft_id": draft_public_id,
        "version": version
    })
    assert r.status_code == 200

    # Test that the sent draft can't be sent again.
    r = api_client.post_data("/send", {
        "draft_id": draft_public_id,
        "version": version
    })
    assert r.status_code == 400

    drafts = api_client.get_data("/drafts")
    assert not drafts

    message = api_client.get_data("/messages/{}".format(draft_public_id))
    assert message["object"] == "message"
예제 #39
0
def test_create_and_get_draft(api_client, example_draft):
    r = api_client.post_data('/drafts', example_draft)
    assert r.status_code == 200

    public_id = json.loads(r.data)['id']
    version = json.loads(r.data)['version']
    assert version == 0

    r = api_client.get_data('/drafts')
    matching_saved_drafts = [draft for draft in r if draft['id'] == public_id]
    assert len(matching_saved_drafts) == 1
    saved_draft = matching_saved_drafts[0]

    assert all(saved_draft[k] == v for k, v in example_draft.iteritems())
예제 #40
0
def test_get_all_drafts(api_client, example_draft):
    r = api_client.post_data("/drafts", example_draft)
    first_public_id = json.loads(r.data)["id"]

    r = api_client.post_data("/drafts", example_draft)
    second_public_id = json.loads(r.data)["id"]

    drafts = api_client.get_data("/drafts")
    assert len(drafts) == 2
    assert first_public_id != second_public_id
    assert {first_public_id,
            second_public_id} == {draft["id"]
                                  for draft in drafts}
    assert all(item["object"] == "draft" for item in drafts)
예제 #41
0
def test_message_folders(db, generic_account):
    # Because we're using the generic_account namespace
    api_client = new_api_client(db, generic_account.namespace)

    # Generic IMAP threads, messages have a 'folders' field
    generic_thread = add_fake_thread(db.session, generic_account.namespace.id)
    generic_message = add_fake_message(db.session,
                                       generic_account.namespace.id,
                                       generic_thread)

    resp_data = api_client.get_data("/threads/{}".format(
        generic_thread.public_id))

    assert resp_data["id"] == generic_thread.public_id
    assert resp_data["object"] == "thread"
    assert "folders" in resp_data and "labels" not in resp_data

    resp_data = api_client.get_data("/messages/{}".format(
        generic_message.public_id))

    assert resp_data["id"] == generic_message.public_id
    assert resp_data["object"] == "message"
    assert "folder" in resp_data and "labels" not in resp_data
예제 #42
0
def test_get_all_drafts(api_client, example_draft):
    r = api_client.post_data('/drafts', example_draft)
    first_public_id = json.loads(r.data)['id']

    r = api_client.post_data('/drafts', example_draft)
    second_public_id = json.loads(r.data)['id']

    drafts = api_client.get_data('/drafts')
    assert len(drafts) == 2
    assert first_public_id != second_public_id
    assert {first_public_id,
            second_public_id} == {draft['id']
                                  for draft in drafts}
    assert all(item['object'] == 'draft' for item in drafts)
예제 #43
0
def test_send_existing_draft(patch_smtp, api_client, example_draft):
    r = api_client.post_data('/drafts', example_draft)
    draft_public_id = json.loads(r.data)['id']
    version = json.loads(r.data)['version']

    r = api_client.post_data('/send', {
        'draft_id': draft_public_id,
        'version': version
    })
    assert r.status_code == 200

    # Test that the sent draft can't be sent again.
    r = api_client.post_data('/send', {
        'draft_id': draft_public_id,
        'version': version
    })
    assert r.status_code == 400

    drafts = api_client.get_data('/drafts')
    assert not drafts

    message = api_client.get_data('/messages/{}'.format(draft_public_id))
    assert message['object'] == 'message'
예제 #44
0
def test_message_events_are_propagated_to_thread(api_client, message):
    """
    Test that a revision to a message's `propagated_attributes` returns a delta
    for the message and for its thread.

    """
    ts = int(time.time() + 22)
    cursor = get_cursor(api_client, ts)

    message = api_client.get_data("/messages/")[0]
    message_id = message["id"]
    assert message["unread"] is True

    thread = api_client.get_data("/threads/{}".format(message["thread_id"]))
    assert thread["unread"] is True

    # Modify a `propagated_attribute` of the message
    message_path = "/messages/{}".format(message_id)
    api_client.put_data(message_path, {"unread": False})

    # Verify that a `message` and a `thread` modify delta is returned
    sync_data = api_client.get_data("/delta?cursor={}".format(cursor))
    deltas = sync_data["deltas"]
    assert len(deltas) == 2

    message_deltas = [d for d in deltas if d["object"] == "message"]
    assert len(message_deltas) == 1
    delta = message_deltas[0]
    assert delta["object"] == "message" and delta["event"] == "modify"
    assert delta["attributes"]["unread"] is False

    thread_deltas = [d for d in deltas if d["object"] == "thread"]
    assert len(thread_deltas) == 1
    delta = thread_deltas[0]
    assert delta["object"] == "thread" and delta["event"] == "modify"
    assert delta["attributes"]["unread"] is False
    assert delta["attributes"]["version"] == thread["version"] + 1
예제 #45
0
def test_api_get(db, api_client, calendar):
    e_data = {
        'title': 'subj',
        'when': {
            'time': 1
        },
        'calendar_id': calendar.public_id,
        'location': 'InboxHQ'
    }
    e_data2 = {
        'title': 'subj2',
        'when': {
            'time': 1
        },
        'calendar_id': calendar.public_id,
        'location': 'InboxHQ'
    }
    api_client.post_data('/events', e_data)
    api_client.post_data('/events', e_data2)

    event_list = api_client.get_data('/events')

    event_ids = [event['id'] for event in event_list]

    c1found = False
    c2found = False
    for c_id in event_ids:
        event = api_client.get_data('/events/' + c_id)

        if event['title'] == 'subj':
            c1found = True

        if event['title'] == 'subj2':
            c2found = True

    assert c1found
    assert c2found
예제 #46
0
def test_api_get(db, api_client, calendar):
    e_data = {
        "title": "subj",
        "when": {
            "time": 1
        },
        "calendar_id": calendar.public_id,
        "location": "NylasHQ",
    }
    e_data2 = {
        "title": "subj2",
        "when": {
            "time": 1
        },
        "calendar_id": calendar.public_id,
        "location": "NylasHQ",
    }
    api_client.post_data("/events", e_data)
    api_client.post_data("/events", e_data2)

    event_list = api_client.get_data("/events")

    event_ids = [event["id"] for event in event_list]

    c1found = False
    c2found = False
    for c_id in event_ids:
        event = api_client.get_data("/events/" + c_id)

        if event["title"] == "subj":
            c1found = True

        if event["title"] == "subj2":
            c2found = True

    assert c1found
    assert c2found
예제 #47
0
def test_message_events_are_propagated_to_thread(api_client, message):
    """
    Test that a revision to a message's `propagated_attributes` returns a delta
    for the message and for its thread.

    """
    ts = int(time.time() + 22)
    cursor = get_cursor(api_client, ts)

    message = api_client.get_data('/messages/')[0]
    message_id = message['id']
    assert message['unread'] is True

    thread = api_client.get_data('/threads/{}'.format(message['thread_id']))
    assert thread['unread'] is True

    # Modify a `propagated_attribute` of the message
    message_path = '/messages/{}'.format(message_id)
    api_client.put_data(message_path, {'unread': False})

    # Verify that a `message` and a `thread` modify delta is returned
    sync_data = api_client.get_data('/delta?cursor={}'.format(cursor))
    deltas = sync_data['deltas']
    assert len(deltas) == 2

    message_deltas = [d for d in deltas if d['object'] == 'message']
    assert len(message_deltas) == 1
    delta = message_deltas[0]
    assert delta['object'] == 'message' and delta['event'] == 'modify'
    assert delta['attributes']['unread'] is False

    thread_deltas = [d for d in deltas if d['object'] == 'thread']
    assert len(thread_deltas) == 1
    delta = thread_deltas[0]
    assert delta['object'] == 'thread' and delta['event'] == 'modify'
    assert delta['attributes']['unread'] is False
    assert delta['attributes']['version'] == thread['version'] + 1
예제 #48
0
def test_api_expand_recurring_before_after(db, api_client, recurring_event):
    event = recurring_event
    starts_after = event.start.replace(weeks=+15)
    ends_before = starts_after.replace(days=+1)

    recur = 'expand_recurring=true&starts_after={}&ends_before={}'.format(
        urlsafe(starts_after), urlsafe(ends_before))
    all_events = api_client.get_data('/events?' + recur)
    assert len(all_events) == 1

    recur = 'expand_recurring=true&starts_after={}&starts_before={}'.format(
        urlsafe(starts_after), urlsafe(ends_before))
    all_events = api_client.get_data('/events?' + recur)
    assert len(all_events) == 1

    recur = 'expand_recurring=true&ends_after={}&starts_before={}'.format(
        urlsafe(starts_after), urlsafe(ends_before))
    all_events = api_client.get_data('/events?' + recur)
    assert len(all_events) == 1

    recur = 'expand_recurring=true&ends_after={}&ends_before={}'.format(
        urlsafe(starts_after), urlsafe(ends_before))
    all_events = api_client.get_data('/events?' + recur)
    assert len(all_events) == 1
예제 #49
0
def test_query_target(db, api_client, thread, default_namespace):
    cat = Category(
        namespace_id=default_namespace.id,
        name="inbox",
        display_name="Inbox",
        type_="label",
    )
    for _ in range(3):
        message = add_fake_message(
            db.session,
            default_namespace.id,
            thread,
            to_addr=[("Bob", "*****@*****.**")],
            from_addr=[("Alice", "*****@*****.**")],
            subject="some subject",
        )
        message.categories.add(cat)
    db.session.commit()

    results = api_client.get_data("/messages?in=inbox")
    assert len(results) == 3

    count = api_client.get_data("/messages?in=inbox&view=count")
    assert count["count"] == 3
예제 #50
0
def test_handle_missing_objects(api_client, db, thread, default_namespace):
    ts = int(time.time() + 22)
    cursor = get_cursor(api_client, ts)

    messages = []
    for _ in range(100):
        messages.append(
            add_fake_message(db.session, default_namespace.id, thread))
    for message in messages:
        db.session.delete(message)
    db.session.commit()
    sync_data = api_client.get_data(
        '/delta?cursor={}&exclude_types=thread'.format(cursor))
    assert len(sync_data['deltas']) == 100
    assert all(delta['event'] == 'delete' for delta in sync_data['deltas'])
예제 #51
0
def test_get_calendar(db, default_namespace, api_client):
    cal = Calendar(namespace_id=default_namespace.id,
                   uid='uid',
                   provider_name='WTF',
                   name='Holidays')
    db.session.add(cal)
    db.session.commit()
    cal_id = cal.public_id
    calendar_item = api_client.get_data('/calendars/{}'.format(cal_id))

    assert calendar_item['account_id'] == default_namespace.public_id
    assert calendar_item['name'] == 'Holidays'
    assert calendar_item['description'] is None
    assert calendar_item['read_only'] is False
    assert calendar_item['object'] == 'calendar'
예제 #52
0
def test_reply_headers_set(db, patch_smtp, api_client, example_draft, thread,
                           message):
    message.message_id_header = '<*****@*****.**>'
    db.session.commit()
    thread_id = api_client.get_data('/threads')[0]['id']

    api_client.post_data('/send', {
        'to': [{
            'email': '*****@*****.**'
        }],
        'thread_id': thread_id
    })
    _, msg = patch_smtp[-1]
    parsed = mime.from_string(msg)
    assert 'In-Reply-To' in parsed.headers
    assert 'References' in parsed.headers
예제 #53
0
def test_reply_headers_set(db, patch_smtp, api_client, example_draft, thread,
                           message):
    message.message_id_header = "<*****@*****.**>"
    db.session.commit()
    thread_id = api_client.get_data("/threads")[0]["id"]

    api_client.post_data("/send", {
        "to": [{
            "email": "*****@*****.**"
        }],
        "thread_id": thread_id
    })
    _, msg = patch_smtp[-1]
    parsed = mime.from_string(msg)
    assert "In-Reply-To" in parsed.headers
    assert "References" in parsed.headers
예제 #54
0
def test_file_filtering(api_client, uploaded_file_ids, draft):
    # Attach the files to a draft and search there
    draft["file_ids"] = uploaded_file_ids
    r = api_client.post_data("/drafts", draft)
    assert r.status_code == 200

    draft_resp = json.loads(r.data)
    assert len(draft_resp["files"]) == len(uploaded_file_ids)
    d_id = draft_resp["id"]

    results = api_client.get_data("/files")
    assert len(results) == len(uploaded_file_ids)

    results = api_client.get_data("/files?message_id={}".format(d_id))

    assert all([d_id in f["message_ids"] for f in results])
    assert len(results) == len(uploaded_file_ids)

    results = api_client.get_data("/files?message_id={}&limit=1".format(d_id))
    assert len(results) == 1

    results = api_client.get_data("/files?message_id={}&offset=2".format(d_id))
    assert len(results) == 3

    results = api_client.get_data("/files?filename=LetMeSendYouEmail.wav")
    assert len(results) == 1

    results = api_client.get_data("/files?content_type=audio%2Fx-wav")
    assert len(results) == 1

    results = api_client.get_data("/files?content_type=image%2Fjpeg")
    assert len(results) == 2

    results = api_client.get_data(
        "/files?content_type=image%2Fjpeg&view=count")
    assert results["count"] == 2

    results = api_client.get_data("/files?content_type=image%2Fjpeg&view=ids")
    assert len(results) == 2
예제 #55
0
def test_get_calendar(db, default_namespace, api_client):
    cal = Calendar(
        namespace_id=default_namespace.id,
        uid="uid",
        provider_name="WTF",
        name="Holidays",
    )
    db.session.add(cal)
    db.session.commit()
    cal_id = cal.public_id
    calendar_item = api_client.get_data("/calendars/{}".format(cal_id))

    assert calendar_item["account_id"] == default_namespace.public_id
    assert calendar_item["name"] == "Holidays"
    assert calendar_item["description"] is None
    assert calendar_item["read_only"] is False
    assert calendar_item["object"] == "calendar"
예제 #56
0
def test_download(api_client, uploaded_file_ids, filename):
    # See comment in uploaded_file_ids()
    original_filename = filename
    if filename == 'piece-jointe.jpg':
        filename = u'pièce-jointe.jpg'
    elif filename == 'andra-moi-ennepe.txt':
        filename = u'ἄνδρα μοι ἔννεπε'

    in_file = api_client.get_data(u'/files?filename={}'.format(filename))[0]
    data = api_client.get_raw('/files/{}/download'.format(in_file['id'])).data

    path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..',
                        'data', original_filename.encode('utf-8'))
    local_data = open(path, 'rb').read()
    local_md5 = md5.new(local_data).digest()
    dl_md5 = md5.new(data).digest()
    assert local_md5 == dl_md5
예제 #57
0
def test_api_expand_recurring(db, api_client, recurring_event):
    event = recurring_event

    events = api_client.get_data('/events?expand_recurring=false')
    assert len(events) == 1
    # Make sure the recurrence info is on the recurring event
    for e in events:
        if e['title'] == 'recurring-weekly':
            assert e.get('recurrence') is not None

    thirty_weeks = event.start.replace(weeks=+30).isoformat()
    starts_after = event.start.replace(days=-1).isoformat()
    recur = 'expand_recurring=true&starts_after={}&ends_before={}'.format(
        urllib.quote_plus(starts_after), urllib.quote_plus(thirty_weeks))
    all_events = api_client.get_data('/events?' + recur)

    if not event.all_day:
        assert len(all_events) == 28

        # the ordering should be correct
        prev = all_events[0]['when']['start_time']
        for e in all_events[1:]:
            assert e['when']['start_time'] > prev
            prev = e['when']['start_time']

            # Check that the parent event recurring id is included
            # too.
            assert e['calendar_id'] == recurring_event.calendar.public_id

        events = api_client.get_data('/events?' + recur + '&view=count')
        assert events.get('count') == 28
    else:
        # Since an all-day event starts at 00:00 we're returning one
        # more event.
        assert len(all_events) == 29
        # the ordering should be correct
        prev = all_events[0]['when']['date']
        for e in all_events[1:]:
            assert e['when']['date'] > prev
            prev = e['when']['date']

            # Check that the parent event recurring id is included
            # too.
            assert e['calendar_id'] == recurring_event.calendar.public_id

        events = api_client.get_data('/events?' + recur + '&view=count')
        assert events.get('count') == 29

    events = api_client.get_data('/events?' + recur + '&limit=5')
    assert len(events) == 5

    events = api_client.get_data('/events?' + recur + '&offset=5')
    assert events[0]['id'] == all_events[5]['id']
예제 #58
0
def test_api_expand_recurring(db, api_client, recurring_event):
    event = recurring_event

    events = api_client.get_data("/events?expand_recurring=false")
    assert len(events) == 1
    # Make sure the recurrence info is on the recurring event
    for e in events:
        if e["title"] == "recurring-weekly":
            assert e.get("recurrence") is not None

    thirty_weeks = event.start.replace(weeks=+30).isoformat()
    starts_after = event.start.replace(days=-1).isoformat()
    recur = "expand_recurring=true&starts_after={}&ends_before={}".format(
        urllib.quote_plus(starts_after), urllib.quote_plus(thirty_weeks))
    all_events = api_client.get_data("/events?" + recur)

    if not event.all_day:
        assert len(all_events) == 28

        # the ordering should be correct
        prev = all_events[0]["when"]["start_time"]
        for e in all_events[1:]:
            assert e["when"]["start_time"] > prev
            prev = e["when"]["start_time"]

            # Check that the parent event recurring id is included
            # too.
            assert e["calendar_id"] == recurring_event.calendar.public_id

        events = api_client.get_data("/events?" + recur + "&view=count")
        assert events.get("count") == 28
    else:
        # Since an all-day event starts at 00:00 we're returning one
        # more event.
        assert len(all_events) == 29
        # the ordering should be correct
        prev = all_events[0]["when"]["date"]
        for e in all_events[1:]:
            assert e["when"]["date"] > prev
            prev = e["when"]["date"]

            # Check that the parent event recurring id is included
            # too.
            assert e["calendar_id"] == recurring_event.calendar.public_id

        events = api_client.get_data("/events?" + recur + "&view=count")
        assert events.get("count") == 29

    events = api_client.get_data("/events?" + recur + "&limit=5")
    assert len(events) == 5

    events = api_client.get_data("/events?" + recur + "&offset=5")
    assert events[0]["id"] == all_events[5]["id"]
예제 #59
0
def test_add_to_read_only_calendar(db, api_client):
    cal_list = api_client.get_data("/calendars")
    ro_cal = None
    for c in cal_list:
        if c["read_only"]:
            ro_cal = c

    assert ro_cal

    e_data = {
        "calendar_id": ro_cal["id"],
        "title": "subj",
        "description": "body1",
        "when": {"time": 1},
        "location": "NylasHQ",
    }
    resp = api_client.post_data("/events", e_data)
    assert resp.status_code == 400
예제 #60
0
def test_api_update_read_only(db, api_client, calendar, default_namespace):
    add_fake_event(db.session, default_namespace.id,
                   calendar=calendar,
                   read_only=True)
    event_list = api_client.get_data('/events')

    read_only_event = None
    for e in event_list:
        if e['read_only']:
            read_only_event = e
            break

    assert read_only_event

    e_id = read_only_event['id']
    e_update_data = {'title': 'new title'}
    e_put_resp = api_client.put_data('/events/' + e_id, e_update_data)
    assert e_put_resp.status_code != 200