def test_delete_tag(api_client, default_namespace, thread):
    post_resp = api_client.post_data('/tags/', {'name': 'foo'})
    tag_resp = json.loads(post_resp.data)
    tag_id = tag_resp['id']

    thread_id = api_client.get_data('/threads')[0]['id']
    api_client.put_data('/threads/{}'.format(thread_id), {'add_tags': ['foo']})

    del_resp = api_client.delete('/tags/' + tag_id)
    assert del_resp.status_code == 200
    tag_data = api_client.get_data('/tags/{}'.format(tag_id))
    assert tag_data['message'] == 'No tag found'

    thread = api_client.get_data('/threads/{}'.format(thread_id))
    assert 'foo' not in [tag['name'] for tag in thread['tags']]

    del_resp = api_client.delete('/tags/!' + tag_id)
    assert del_resp.status_code == 400
    assert json.loads(del_resp.data)['message'].startswith('Invalid id')

    del_resp = api_client.delete('/tags/0000000000000000000000000')
    assert del_resp.status_code == 404

    del_resp = api_client.delete('/tags/inbox')
    assert del_resp.status_code == 400
    assert 'user-created' in json.loads(del_resp.data)['message']
Exemple #2
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
def test_unread_cascades_to_messages(log, api_client, default_account, thread,
                                     message):
    thread_id = api_client.get_data('/threads/')[0]['id']
    thread_path = '/threads/{}'.format(thread_id)
    api_client.put_data(thread_path, {'add_tags': ['unread']})
    messages = api_client.get_data('/messages?thread_id={}'.format(thread_id))
    assert all([msg['unread'] for msg in messages])

    api_client.put_data(thread_path, {'remove_tags': ['unread']})
    messages = api_client.get_data('/messages?thread_id={}'.format(thread_id))
    assert not any([msg['unread'] for msg in messages])
def test_events_are_condensed(api_client):
    """Test that multiple revisions of the same object are rolled up in the
    delta response."""
    ts = int(time.time())
    api_client.post_data('/tags/', {'name': 'foo'})
    cursor = get_cursor(api_client, ts)
    thread_id = api_client.get_data('/threads/')[0]['id']
    thread_path = '/threads/{}'.format(thread_id)
    api_client.put_data(thread_path, {'add_tags': ['foo']})
    api_client.put_data(thread_path, {'remove_tags': ['foo']})
    sync_data = api_client.get_data('/delta?cursor={}'.format(cursor))
    assert len(sync_data['deltas']) == 2
Exemple #5
0
def test_unread_cascades_to_messages(patch_network_functions, log, api_client,
                                     syncback_service, default_account):
    thread_id = api_client.get_data('/threads/')[0]['id']
    thread_path = '/threads/{}'.format(thread_id)
    api_client.put_data(thread_path, {'add_tags': ['unread']})
    gevent.sleep(3)
    messages = api_client.get_data('/messages?thread_id={}'.format(thread_id))
    assert all([msg['unread'] for msg in messages])

    api_client.put_data(thread_path, {'remove_tags': ['unread']})
    gevent.sleep(3)
    messages = api_client.get_data('/messages?thread_id={}'.format(thread_id))
    assert not any([msg['unread'] for msg in messages])
Exemple #6
0
def test_add_remove_tags(api_client):
    assert 'foo' not in [tag['name'] for tag in api_client.get_data('/tags/')]
    assert 'bar' not in [tag['name'] for tag in api_client.get_data('/tags/')]

    api_client.post_data('/tags/', {'name': 'foo'})
    api_client.post_data('/tags/', {'name': 'bar'})

    thread_id = api_client.get_data('/threads/')[0]['id']
    thread_path = '/threads/{}'.format(thread_id)
    api_client.put_data(thread_path, {'add_tags': ['foo']})
    api_client.put_data(thread_path, {'add_tags': ['bar']})

    tag_names = [tag['name'] for tag in
                 api_client.get_data(thread_path)['tags']]
    assert 'foo' in tag_names
    assert 'bar' in tag_names

    # Check that tag was only applied to this thread
    another_thread_id = api_client.get_data('/threads/')[1]['id']
    tag_names = get_tag_names(
        api_client.get_data('/threads/{}'.format(another_thread_id)))
    assert 'foo' not in tag_names

    api_client.put_data(thread_path, {'remove_tags': ['foo']})
    api_client.put_data(thread_path, {'remove_tags': ['bar']})
    tag_names = get_tag_names(api_client.get_data(thread_path))
    assert 'foo' not in tag_names
    assert 'bar' not in tag_names
def test_events_are_condensed(api_client):
    """Test that multiple revisions of the same object are rolled up in the
    delta response."""
    ts = int(time.time())
    cursor = get_cursor(api_client, ts)

    # Create, then modify a tag; then modify it again
    tag = json.loads(api_client.post_data('/tags/', {'name': 'foo'}).data)
    tag_id = tag['id']
    api_client.put_data('/tags/{}'.format(tag_id), {'name': 'bar'})
    api_client.put_data('/tags/{}'.format(tag_id), {'name': 'baz'})

    # Modify a thread, then modify it again
    thread_id = api_client.get_data('/threads/')[0]['id']
    thread_path = '/threads/{}'.format(thread_id)
    api_client.put_data(thread_path, {'add_tags': [tag_id]})
    api_client.put_data(thread_path, {'remove_tags': [tag_id]})

    sync_data = api_client.get_data('/delta?cursor={}'.format(cursor))
    assert len(sync_data['deltas']) == 3
    first_delta = sync_data['deltas'][0]
    assert first_delta['object'] == 'tag' and first_delta['event'] == 'create'

    # Check that successive modifies are condensed.

    second_delta = sync_data['deltas'][1]
    assert (second_delta['object'] == 'tag' and
            second_delta['event'] == 'modify')
    assert second_delta['attributes']['name'] == 'baz'

    third_delta = sync_data['deltas'][2]
    assert (third_delta['object'] == 'thread' and
            third_delta['event'] == 'modify')
Exemple #8
0
def test_api_update_title(db, api_client):
    acct = db.session.query(Account).filter_by(id=ACCOUNT_ID).one()
    ns_id = acct.namespace.public_id

    e_data = {
        'title': '',
        'when': {'time': 1407542195},
    }

    e_resp = api_client.post_data('/events', e_data, ns_id)
    e_resp_data = json.loads(e_resp.data)
    assert e_resp_data['object'] == 'event'
    assert e_resp_data['namespace_id'] == acct.namespace.public_id
    assert e_resp_data['title'] == e_data['title']
    assert e_resp_data['when']['time'] == e_data['when']['time']
    assert 'id' in e_resp_data
    e_id = e_resp_data['id']

    e_update_data = {'title': 'new title'}
    e_put_resp = api_client.put_data('/events/' + e_id, e_update_data, ns_id)
    e_put_data = json.loads(e_put_resp.data)

    assert e_put_data['object'] == 'event'
    assert e_put_data['namespace_id'] == acct.namespace.public_id
    assert e_put_data['id'] == e_id
    assert e_put_data['title'] == 'new title'
    assert e_put_data['when']['object'] == 'time'
    assert e_put_data['when']['time'] == e_data['when']['time']
Exemple #9
0
def test_api_update_invalid(db, api_client):
    acct = db.session.query(Account).filter_by(id=ACCOUNT_ID).one()
    ns_id = acct.namespace.public_id
    e_update_data = {'title': 'new title'}
    e_id = generate_public_id()
    e_put_resp = api_client.put_data('/events/' + e_id, e_update_data, ns_id)
    assert e_put_resp.status_code != 200
Exemple #10
0
def test_can_only_update_user_tags(api_client):
    r = api_client.get_data('/tags/unread')
    assert r['name'] == 'unread'
    assert r['id'] == 'unread'

    r = api_client.put_data('/tags/unread', {'name': 'new name'})
    assert r.status_code == 403
Exemple #11
0
def test_delete_draft(api_client):
    original_draft = {
        'subject': 'parent 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']

    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']

    r = api_client.delete('/drafts/{}'.format(updated_public_id),
                          {'version': updated_version})

    # Check that drafts were deleted
    drafts = api_client.get_data('/drafts')
    assert not drafts
def test_actions_dont_duplicate(patch_network_functions, api_client, db,
                                syncback_service, default_account):
    """ Test that a client invocation that would cause the same action to
        be scheduled multiple times only inserts one row into ActionLog.
    """
    from inbox.models import ActionLog

    thread_id = api_client.get_data('/threads/')[0]['id']
    thread_path = '/threads/{}'.format(thread_id)

    # Make sure tags are removed to start with
    api_client.put_data(thread_path, {'add_tags': ['archive'],
                                      'remove_tags': ['inbox']})

    action_log_count = db.session.query(ActionLog).count()
    assert action_log_count == 1
def test_api_update_title(db, api_client, calendar, default_account):
    e_data = {
        'title': '',
        'calendar_id': calendar.public_id,
        'when': {'time': 1407542195},
    }

    e_resp = api_client.post_data('/events', e_data)
    e_resp_data = json.loads(e_resp.data)
    assert e_resp_data['object'] == 'event'
    assert e_resp_data['namespace_id'] == default_account.namespace.public_id
    assert e_resp_data['title'] == e_data['title']
    assert e_resp_data['when']['time'] == e_data['when']['time']
    assert 'id' in e_resp_data
    e_id = e_resp_data['id']

    e_update_data = {'title': 'new title'}
    e_put_resp = api_client.put_data('/events/' + e_id, e_update_data)
    e_put_data = json.loads(e_put_resp.data)

    assert e_put_data['object'] == 'event'
    assert e_put_data['namespace_id'] == default_account.namespace.public_id
    assert e_put_data['id'] == e_id
    assert e_put_data['title'] == 'new title'
    assert e_put_data['when']['object'] == 'time'
    assert e_put_data['when']['time'] == e_data['when']['time']
def test_api_remove_participant(events_provider, event_sync,
                                db, api_client):
    acct = db.session.query(Account).filter_by(id=ACCOUNT_ID).one()
    ns_id = acct.namespace.public_id

    e_data = {
        'subject': 'Friday Office Party',
        'start': 1407542195,
        'end': 1407543195,
        'busy': False,
        'all_day': False,
        'participants': [{'email': '*****@*****.**'},
                         {'email': '*****@*****.**'},
                         {'email': '*****@*****.**'},
                         {'email': '*****@*****.**'},
                         {'email': '*****@*****.**'}]
    }

    e_resp = api_client.post_data('/events', e_data, ns_id)
    e_resp_data = json.loads(e_resp.data)
    assert len(e_resp_data['participants']) == 5
    for i, p in enumerate(e_resp_data['participants']):
        assert p['email'] == e_data['participants'][i]['email']
        assert p['name'] is None

    event_id = e_resp_data['id']
    e_data['participants'].pop()
    e_resp = api_client.put_data('/events/' + event_id, e_data, ns_id)
    e_resp_data = json.loads(e_resp.data)
    assert len(e_resp_data['participants']) == 4
    for i, p in enumerate(e_resp_data['participants']):
        assert p['email'] == e_data['participants'][i]['email']
        assert p['name'] is None
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_remove_participant(db, api_client):
    acct = db.session.query(Account).filter_by(id=ACCOUNT_ID).one()
    ns_id = acct.namespace.public_id

    e_data = {
        'title': 'Friday Office Party',
        'when': {'time': 1407542195},
        'participants': [{'email': '*****@*****.**'},
                         {'email': '*****@*****.**'},
                         {'email': '*****@*****.**'},
                         {'email': '*****@*****.**'},
                         {'email': '*****@*****.**'}]
    }

    e_resp = api_client.post_data('/events', e_data, ns_id)
    e_resp_data = json.loads(e_resp.data)
    assert len(e_resp_data['participants']) == 5
    for i, p in enumerate(e_resp_data['participants']):
        res = [e for e in e_resp_data['participants']
               if e['email'] == p['email']]
        assert len(res) == 1
        assert res[0]['name'] is None

    event_id = e_resp_data['id']
    e_data['participants'].pop()
    e_resp = api_client.put_data('/events/' + event_id, e_data, ns_id)
    e_resp_data = json.loads(e_resp.data)
    assert len(e_resp_data['participants']) == 4
    for i, p in enumerate(e_resp_data['participants']):
        res = [e for e in e_resp_data['participants']
               if e['email'] == p['email']]
        assert len(res) == 1
        assert p['name'] is None
Exemple #17
0
def test_update_draft(api_client):
    original_draft = {
        'subject': 'parent 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']

    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 and \
        updated_version != version

    drafts = api_client.get_data('/drafts')
    assert len(drafts) == 1
    assert drafts[0]['id'] == updated_public_id
Exemple #18
0
def test_move_to_read_only_calendar(db, api_client):
    acct = db.session.query(Account).filter_by(id=ACCOUNT_ID).one()
    ns_id = acct.namespace.public_id
    calendar_list = api_client.get_data('/calendars', ns_id)

    read_only_calendar = None
    writeable_calendar = None
    writeable_event = None
    for c in calendar_list:
        if c['read_only']:
            read_only_calendar = c
        else:
            writeable_calendar = c
            for e_id in c['event_ids']:
                e = api_client.get_data('/events/' + e_id, ns_id)
                if not e['read_only']:
                    writeable_event = e
                    break

    assert read_only_calendar
    assert writeable_event
    assert writeable_calendar
    e_id = writeable_event['id']

    e_data = {'calendar_id': read_only_calendar['id']}
    resp = api_client.put_data('/events/' + e_id, e_data, ns_id)
    assert resp.status_code != 200
Exemple #19
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
Exemple #20
0
def test_update_calendar(db, api_client):
    acct = db.session.query(Account).filter_by(id=ACCOUNT_ID).one()
    ns_id = acct.namespace.public_id

    c_data = {'name': 'Vacation'}

    resp = api_client.post_data('/calendars', c_data, ns_id)
    resp_data = json.loads(resp.data)

    cal_id = resp_data['id']

    c_update_data = {'name': 'OOO'}
    resp = api_client.put_data('/calendars/' + cal_id, c_update_data, ns_id)
    c_put_data = json.loads(resp.data)
    assert resp.status_code == 200
    assert c_put_data['namespace_id'] == ns_id
    assert c_put_data['name'] == c_update_data['name']
    assert c_put_data['description'] is None
    assert c_put_data['read_only'] is False
    assert c_put_data['object'] == 'calendar'
    assert c_put_data['event_ids'] == []

    resp_data = api_client.get_data('/calendars/' + cal_id, ns_id)
    assert resp_data['namespace_id'] == ns_id
    assert resp_data['name'] == c_update_data['name']
    assert resp_data['description'] is None
    assert resp_data['read_only'] is False
    assert resp_data['object'] == 'calendar'
    assert resp_data['event_ids'] == []

    cal = db.session.query(Calendar).filter_by(public_id=cal_id).one()
    db.session.delete(cal)
    db.session.commit()
def test_delete_draft(api_client):
    original_draft = {"subject": "parent 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"]

    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"]

    r = api_client.delete("/drafts/{}".format(updated_public_id), {"version": updated_version})

    # Check that drafts were deleted
    drafts = api_client.get_data("/drafts")
    assert not drafts

    # Check that no orphaned threads are around
    threads = api_client.get_data("/threads?subject=parent%20draft")
    assert not threads
    threads = api_client.get_data("/threads?subject=updated%20draft")
    assert not threads

    # And check that threads aren't deleted if they still have messages.
    thread_public_id = api_client.get_data("/threads")[0]["id"]
    reply_draft = {"subject": "test reply", "body": "test reply", "thread_id": thread_public_id}
    r = api_client.post_data("/drafts", reply_draft)
    public_id = json.loads(r.data)["id"]
    version = json.loads(r.data)["version"]
    thread = api_client.get_data("/threads/{}".format(thread_public_id))
    assert "drafts" in [t["name"] for t in thread["tags"]]
    api_client.delete("/drafts/{}".format(public_id), {"version": version})
    thread = api_client.get_data("/threads/{}".format(thread_public_id))
    assert thread
    assert "drafts" not in [t["name"] for t in thread["tags"]]
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
def test_update_draft(api_client):
    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

    # Sleep so that timestamp on updated draft is different.
    gevent.sleep(1)

    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"]
Exemple #24
0
def test_event_generation(api_client):
    """Test that deltas are returned in response to client sync API calls.
    Doesn't test formatting of individual deltas in the response."""
    ts = int(time.time())
    cursor = get_cursor(api_client, ts)

    sync_data = api_client.get_data('/delta?cursor={}'.format(cursor))
    assert len(sync_data['deltas']) == 0
    assert sync_data['cursor_end'] == cursor
    assert sync_data['cursor_end'] == sync_data['cursor_start']

    api_client.post_data('/tags/', {'name': 'foo'})

    sync_data = api_client.get_data('/delta?cursor={}'.format(cursor))
    assert len(sync_data['deltas']) == 1
    api_client.post_data('/contacts/', {'name': 'test',
                                        'email': '*****@*****.**'})

    sync_data = api_client.get_data('/delta?cursor={}'.format(cursor))
    assert len(sync_data['deltas']) == 2

    thread_id = api_client.get_data('/threads/')[0]['id']
    thread_path = '/threads/{}'.format(thread_id)
    api_client.put_data(thread_path, {'add_tags': ['foo']})

    sync_data = api_client.get_data('/delta?cursor={}'.format(cursor))
    assert len(sync_data['deltas']) == 3

    time.sleep(1)

    ts = int(time.time())

    # Test result limiting
    for i in range(1, 10):
        thread_id = api_client.get_data('/threads/')[i]['id']
        thread_path = '/threads/{}'.format(thread_id)
        api_client.put_data(thread_path, {'add_tags': ['foo']})

    cursor = get_cursor(api_client, ts)

    sync_data = api_client.get_data('/delta?cursor={0}&limit={1}'.
                                    format(cursor, 8))
    assert len(sync_data['deltas']) == 8

    cursor = sync_data['cursor_end']
    sync_data = api_client.get_data('/delta?cursor={0}'.format(cursor))
    assert len(sync_data['deltas']) == 1
Exemple #25
0
def test_tag_permissions(api_client, db):
    from inbox.models import Tag
    thread_id = api_client.get_data('/threads/')[0]['id']
    thread_path = '/threads/{}'.format(thread_id)
    for canonical_name in Tag.RESERVED_TAG_NAMES:
        r = api_client.put_data(thread_path, {'add_tags': [canonical_name]})
        if canonical_name in Tag.USER_MUTABLE_TAGS:
            assert r.status_code == 200
        else:
            assert r.status_code == 400

    # Test special permissions of the 'unseen' tag
    r = api_client.put_data(thread_path, {'add_tags': ['unseen']})
    assert r.status_code == 400

    r = api_client.put_data(thread_path, {'remove_tags': ['unseen']})
    assert r.status_code == 200
Exemple #26
0
def test_move_event(db, api_client):
    acct = db.session.query(Account).filter_by(id=ACCOUNT_ID).one()
    ns_id = acct.namespace.public_id
    calendar_list = api_client.get_data('/calendars', ns_id)

    writeable_calendar = None
    writeable_event = None
    for c in calendar_list:
        if not c['read_only']:
            writeable_calendar = c
            for e_id in c['event_ids']:
                e = api_client.get_data('/events/' + e_id, ns_id)
                if not e['read_only']:
                    writeable_event = e
                    break

    assert writeable_event
    assert writeable_calendar
    e_id = writeable_event['id']

    c_data = {'name': 'Birthdays'}
    resp = api_client.post_data('/calendars', c_data, ns_id)
    resp_data = json.loads(resp.data)
    cal_id = resp_data['id']

    e_data = {'calendar_id': cal_id}
    resp = api_client.put_data('/events/' + e_id, e_data, ns_id)
    assert resp.status_code == 200

    event = api_client.get_data('/events/' + e_id, ns_id)
    assert event['calendar_id'] == cal_id

    e_data = {'calendar_id': writeable_calendar['id']}
    resp = api_client.put_data('/events/' + e_id, e_data, ns_id)
    assert resp.status_code == 200

    event = api_client.get_data('/events/' + e_id, ns_id)
    assert event['calendar_id'] == writeable_calendar['id']

    cal = db.session.query(Calendar).filter_by(public_id=cal_id).one()
    db.session.delete(cal)
    db.session.commit()
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
Exemple #28
0
def test_update_to_nonexistent_draft(api_client):
    updated_draft = {
        'subject': 'updated draft',
        'body': 'updated draft',
        'version': 'notarealversion'
    }

    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
Exemple #29
0
def test_read_update_tags(api_client):
    r = api_client.post_data('/tags/', {'name': 'foo'})
    public_id = json.loads(r.data)['id']

    tag_data = api_client.get_data('/tags/{}'.format(public_id))
    assert tag_data['name'] == 'foo'
    assert tag_data['id'] == public_id
    tag_ns_id = tag_data['namespace_id']

    r = api_client.put_data('/tags/{}'.format(public_id), {'name': 'bar'})
    assert json.loads(r.data)['name'] == 'bar'

    # include namespace
    r = api_client.put_data('/tags/{}'.format(public_id),
                            {'name': 'bar', 'namepace_id': tag_ns_id})
    assert json.loads(r.data)['name'] == 'bar'

    updated_tag_data = api_client.get_data('/tags/{}'.format(public_id))
    assert updated_tag_data['name'] == 'bar'
    assert updated_tag_data['id'] == public_id
def test_api_update_participant_status(events_provider, event_sync,
                                       db, api_client):
    acct = db.session.query(Account).filter_by(id=ACCOUNT_ID).one()
    ns_id = acct.namespace.public_id

    e_data = {
        'subject': 'Friday Office Party',
        'start': 1407542195,
        'end': 1407543195,
        'busy': False,
        'all_day': False,
        'participants': [{'email': '*****@*****.**'},
                         {'email': '*****@*****.**'},
                         {'email': '*****@*****.**'},
                         {'email': '*****@*****.**'},
                         {'email': '*****@*****.**'}]
    }

    e_resp = api_client.post_data('/events', e_data, ns_id)
    e_resp_data = json.loads(e_resp.data)
    assert len(e_resp_data['participants']) == 5
    for i, p in enumerate(e_resp_data['participants']):
        assert p['email'] == e_data['participants'][i]['email']
        assert p['name'] is None

    event_id = e_resp_data['id']

    update_data = {
        'participants': [{'email': '*****@*****.**',
                          'status': 'yes'},
                         {'email': '*****@*****.**',
                          'status': 'no'},
                         {'email': '*****@*****.**',
                          'status': 'maybe'},
                         {'email': '*****@*****.**'},
                         {'email': '*****@*****.**'}]
    }

    e_resp = api_client.put_data('/events/' + event_id, update_data, ns_id)
    e_resp_data = json.loads(e_resp.data)

    # Make sure that nothing changed that we didn't specify
    assert e_resp_data['subject'] == 'Friday Office Party'
    assert e_resp_data['start'] == 1407542195
    assert e_resp_data['end'] == 1407543195
    assert e_resp_data['busy'] is False
    assert e_resp_data['all_day'] is False

    assert len(e_resp_data['participants']) == 5
    expected = ['yes', 'no', 'maybe', 'awaiting', 'awaiting']
    for i, p in enumerate(e_resp_data['participants']):
        assert p['email'] == e_data['participants'][i]['email']
        assert p['status'] == expected[i]
        assert p['name'] is None
Exemple #31
0
def test_delete_draft(api_client):
    original_draft = {'subject': 'parent 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']

    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']

    r = api_client.delete('/drafts/{}'.format(updated_public_id),
                          {'version': updated_version})

    # Check that drafts were deleted
    drafts = api_client.get_data('/drafts')
    assert not drafts

    # Check that no orphaned threads are around
    threads = api_client.get_data('/threads?subject=parent%20draft')
    assert not threads
    threads = api_client.get_data('/threads?subject=updated%20draft')
    assert not threads

    # And check that threads aren't deleted if they still have messages.
    thread_public_id = api_client.get_data('/threads')[0]['id']
    reply_draft = {
        'subject': 'test reply',
        'body': 'test reply',
        'thread_id': thread_public_id
    }
    r = api_client.post_data('/drafts', reply_draft)
    public_id = json.loads(r.data)['id']
    version = json.loads(r.data)['version']
    thread = api_client.get_data('/threads/{}'.format(thread_public_id))
    assert 'drafts' in [t['name'] for t in thread['tags']]
    api_client.delete('/drafts/{}'.format(public_id), {'version': version})
    thread = api_client.get_data('/threads/{}'.format(thread_public_id))
    assert thread
    assert 'drafts' not in [t['name'] for t in thread['tags']]
def test_api_event_when_update(db, api_client, calendar):
    acct = db.session.query(Account).filter_by(id=ACCOUNT_ID).one()
    ns_id = acct.namespace.public_id
    e_data = {
        'title': 'Friday Office Party',
        'location': 'home',
        'calendar_id': calendar.public_id,
    }

    e_data['when'] = {'time': 0}
    e_resp_data = _verify_create(ns_id, api_client, e_data)
    e_id = e_resp_data['id']

    e_update_data = {'when': {'time': 1}}
    e_put_resp = api_client.put_data('/events/' + e_id, e_update_data, ns_id)
    e_put_data = json.loads(e_put_resp.data)
    assert e_put_data['when']['object'] == 'time'
    assert e_put_data['when']['time'] == e_update_data['when']['time']
def test_api_remove_participant(db, api_client):
    acct = db.session.query(Account).filter_by(id=ACCOUNT_ID).one()
    ns_id = acct.namespace.public_id

    e_data = {
        'title':
        'Friday Office Party',
        'when': {
            'time': 1407542195
        },
        'participants': [{
            'email': '*****@*****.**'
        }, {
            'email': '*****@*****.**'
        }, {
            'email': '*****@*****.**'
        }, {
            'email': '*****@*****.**'
        }, {
            'email': '*****@*****.**'
        }]
    }

    e_resp = api_client.post_data('/events', e_data, ns_id)
    e_resp_data = json.loads(e_resp.data)
    assert len(e_resp_data['participants']) == 5
    for i, p in enumerate(e_resp_data['participants']):
        res = [
            e for e in e_resp_data['participants'] if e['email'] == p['email']
        ]
        assert len(res) == 1
        assert res[0]['name'] is None

    event_id = e_resp_data['id']
    e_data['participants'].pop()
    e_resp = api_client.put_data('/events/' + event_id, e_data, ns_id)
    e_resp_data = json.loads(e_resp.data)
    assert len(e_resp_data['participants']) == 4
    for i, p in enumerate(e_resp_data['participants']):
        res = [
            e for e in e_resp_data['participants'] if e['email'] == p['email']
        ]
        assert len(res) == 1
        assert p['name'] is None
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
Exemple #35
0
def test_read_implies_seen(api_client, db):
    thread_id = api_client.get_data('/threads/')[0]['id']
    thread_path = '/threads/{}'.format(thread_id)
    # Do some setup: cheat by making sure the unseen and unread tags are
    # already on the thread.
    from inbox.models import Namespace, Thread
    namespace = db.session.query(Namespace).first()
    unseen_tag = namespace.tags['unseen']
    unread_tag = namespace.tags['unread']
    thread = db.session.query(Thread).filter_by(public_id=thread_id).one()
    thread.tags.add(unseen_tag)
    thread.tags.add(unread_tag)
    db.session.commit()

    r = api_client.get_data(thread_path)
    assert {'unread', 'unseen'}.issubset({tag['id'] for tag in r['tags']})

    r = api_client.put_data(thread_path, {'remove_tags': ['unread']})
    r = api_client.get_data(thread_path)
    assert not any(tag['id'] in ['unread', 'unseen'] for tag in r['tags'])
Exemple #36
0
def test_event_generation(api_client):
    """Tests that deltas are returned in response to client sync API calls.
    Doesn't test formatting of individual deltas in the response."""
    ts = int(time.time())
    api_client.post_data('/tags/', {'name': 'foo'})

    cursor_response = api_client.post_data('/delta/generate_cursor',
                                           {'start': ts})
    cursor = json.loads(cursor_response.data)['cursor']

    sync_data = api_client.get_data('/delta?cursor={}'.format(cursor))
    assert len(sync_data['deltas']) == 1
    api_client.post_data('/contacts/', {
        'name': 'test',
        'email': '*****@*****.**'
    })

    sync_data = api_client.get_data('/delta?cursor={}'.format(cursor))
    assert len(sync_data['deltas']) == 2

    thread_id = api_client.get_data('/threads/')[0]['id']
    thread_path = '/threads/{}'.format(thread_id)
    api_client.put_data(thread_path, {'add_tags': ['foo']})

    sync_data = api_client.get_data('/delta?cursor={}'.format(cursor))
    assert len(sync_data['deltas']) == 3

    time.sleep(1)

    ts = int(time.time())

    # Test result limiting
    for _ in range(5):
        api_client.put_data(thread_path, {'remove_tags': ['foo']})
        api_client.put_data(thread_path, {'add_tags': ['foo']})

    cursor_response = api_client.post_data('/delta/generate_cursor',
                                           {'start': ts})
    cursor = json.loads(cursor_response.data)['cursor']

    sync_data = api_client.get_data('/delta?cursor={0}&limit={1}'.format(
        cursor, 8))
    assert len(sync_data['deltas']) == 8

    cursor = sync_data['cursor_end']
    sync_data = api_client.get_data('/delta?cursor={0}'.format(cursor))
    assert len(sync_data['deltas']) == 2
Exemple #37
0
def test_delete_draft(api_client):
    original_draft = {'subject': 'parent 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']

    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']

    r = api_client.delete('/drafts/{}'.format(updated_public_id),
                          {'version': updated_version})

    # Check that drafts were deleted
    drafts = api_client.get_data('/drafts')
    assert not drafts
Exemple #38
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
Exemple #39
0
def test_update_draft(api_client):
    original_draft = {'subject': 'parent 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']

    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 and \
        updated_version != version

    drafts = api_client.get_data('/drafts')
    assert len(drafts) == 1
    assert drafts[0]['id'] == updated_public_id
def test_api_update_invalid(db, api_client, calendar):
    e_update_data = {'title': 'new title'}
    e_id = generate_public_id()
    e_put_resp = api_client.put_data('/events/' + e_id, e_update_data)
    assert e_put_resp.status_code != 200
def test_api_update_participant_status(db, api_client):
    acct = db.session.query(Account).filter_by(id=ACCOUNT_ID).one()
    ns_id = acct.namespace.public_id

    e_data = {
        'title':
        'Friday Office Party',
        'when': {
            'time': 1407542195
        },
        'participants': [{
            'email': '*****@*****.**'
        }, {
            'email': '*****@*****.**'
        }, {
            'email': '*****@*****.**'
        }, {
            'email': '*****@*****.**'
        }, {
            'email': '*****@*****.**'
        }]
    }

    e_resp = api_client.post_data('/events', e_data, ns_id)
    e_resp_data = json.loads(e_resp.data)
    assert len(e_resp_data['participants']) == 5
    for i, p in enumerate(e_resp_data['participants']):
        res = [e for e in e_data['participants'] if e['email'] == p['email']]
        assert len(res) == 1
        assert p['name'] is None

    event_id = e_resp_data['id']

    update_data = {
        'participants': [{
            'email': '*****@*****.**',
            'status': 'yes'
        }, {
            'email': '*****@*****.**',
            'status': 'no'
        }, {
            'email': '*****@*****.**',
            'status': 'maybe'
        }, {
            'email': '*****@*****.**'
        }, {
            'email': '*****@*****.**'
        }]
    }

    e_resp = api_client.put_data('/events/' + event_id, update_data, ns_id)
    e_resp_data = json.loads(e_resp.data)

    # Make sure that nothing changed that we didn't specify
    assert e_resp_data['title'] == 'Friday Office Party'
    assert e_resp_data['when']['time'] == 1407542195

    assert len(e_resp_data['participants']) == 5
    for i, p in enumerate(e_resp_data['participants']):
        res = [e for e in e_data['participants'] if e['email'] == p['email']]
        assert len(res) == 1
        assert p['name'] is None
Exemple #42
0
def test_create_draft_with_attachments(api_client, attachments, example_draft):
    attachment_ids = []
    upload_path = api_client.full_path('/files')
    for filename, path in attachments:
        data = {'file': (open(path, 'rb'), filename)}
        r = api_client.client.post(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']
    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
    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

    threads_with_drafts = api_client.get_data('/threads?tag=drafts')
    assert len(threads_with_drafts) == 1

    # Check that thread also gets the attachment tag
    thread_tags = threads_with_drafts[0]['tags']
    assert any('attachment' == tag['name'] for tag in thread_tags)

    # 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
    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
    returned_draft = json.loads(r.data)

    # 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
Exemple #43
0
def test_actions_syncback(patch_network_functions, api_client, db,
                          syncback_service, default_account):
    """Adds and removes tags that should trigger syncback actions, and check
    that the appropriate actions get spawned (but doesn't test the
    implementation of the actual syncback methods in inbox.actions).
    """
    from inbox.models import ActionLog

    thread_id = api_client.get_data('/threads/')[0]['id']
    thread_path = '/threads/{}'.format(thread_id)

    # Make sure tags are removed to start with
    api_client.put_data(thread_path, {'remove_tags': ['unread']})
    api_client.put_data(thread_path, {'remove_tags': ['archive']})
    api_client.put_data(thread_path, {'remove_tags': ['starred']})

    action_log_entries = db.session.query(ActionLog)
    assert all(log_entry.status == 'pending'
               for log_entry in action_log_entries)
    gevent.sleep()

    # Add and remove tags that should trigger actions

    api_client.put_data(thread_path, {'add_tags': ['unread']})
    api_client.put_data(thread_path, {'remove_tags': ['unread']})
    gevent.sleep()

    api_client.put_data(thread_path, {'add_tags': ['archive']})
    api_client.put_data(thread_path, {'remove_tags': ['archive']})
    gevent.sleep()

    api_client.put_data(thread_path, {'add_tags': ['starred']})
    api_client.put_data(thread_path, {'remove_tags': ['starred']})

    gevent.sleep(2)

    action_log_entries = db.session.query(ActionLog)
    assert ({log_entry.action
             for log_entry in action_log_entries} == {
                 'mark_read', 'mark_unread', 'archive', 'unarchive', 'star',
                 'unstar'
             })
    assert all(
        [log_entry.status == 'successful' for log_entry in action_log_entries])