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']
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
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])
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')
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']
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
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
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
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_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
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_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"]
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
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
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
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
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
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
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'])
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
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_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_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
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
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])