def test_write_endpoints(db, setup_account, api_client, default_account): # Write operations (create, update, delete) succeed. r = api_client.post_data( '/drafts', data={ 'body': '<html><body><h2>Sea, birds and sand.</h2></body></html>' }) assert r.status_code == 200 draft_id = json.loads(r.data)['id'] endpoint = '/messages/{}'.format(setup_account['message']) r = api_client.put_data(endpoint, data={"starred": True}) assert r.status_code == 200 endpoint = '/events/{}'.format(setup_account['event']) r = api_client.delete(endpoint) assert r.status_code == 200 default_account.sync_state = 'invalid' db.session.commit() # Write operations fail with an HTTP 403. r = api_client.post_data('/labels', data={"display_name": "Neu!"}) assert r.status_code == 403 endpoint = '/threads/{}'.format(setup_account['thread']) r = api_client.put_data(endpoint, data={"starred": True}) assert r.status_code == 403 endpoint = '/drafts/{}'.format(draft_id) r = api_client.delete(endpoint) assert r.status_code == 403
def test_write_endpoints(db, setup_account, api_client, default_account): # Write operations (create, update, delete) succeed. r = api_client.post_data("/drafts", data={"body": "<html><body><h2>Sea, birds and sand.</h2></body></html>"}) assert r.status_code == 200 draft_id = json.loads(r.data)["id"] endpoint = "/messages/{}".format(setup_account["message"]) r = api_client.put_data(endpoint, data={"starred": True}) assert r.status_code == 200 endpoint = "/events/{}".format(setup_account["event"]) r = api_client.delete(endpoint) assert r.status_code == 200 default_account.sync_state = "invalid" db.session.commit() # Write operations fail with an HTTP 403. r = api_client.post_data("/labels", data={"display_name": "Neu!"}) assert r.status_code == 403 endpoint = "/threads/{}".format(setup_account["thread"]) r = api_client.put_data(endpoint, data={"starred": True}) assert r.status_code == 403 endpoint = "/drafts/{}".format(draft_id) r = api_client.delete(endpoint) assert r.status_code == 403
def test_send_draft(db, api_client, example_draft, default_account): 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'] r = api_client.post_data('/send', {'draft_id': public_id, 'version': version}) assert r.status_code == 200 draft = api_client.get_data('/drafts/{}'.format(public_id)) assert draft is not None assert draft['object'] != 'draft' with crispin_client(default_account.id, default_account.provider) as c: criteria = ['NOT DELETED', 'SUBJECT "{0}"'.format( example_draft['subject'])] c.conn.select_folder(default_account.drafts_folder.name, readonly=False) draft_uids = c.conn.search(criteria) assert not draft_uids, 'Message still in Drafts folder' c.conn.select_folder(default_account.sent_folder.name, readonly=False) sent_uids = c.conn.search(criteria) assert sent_uids, 'Message missing from Sent folder' c.conn.delete_messages(sent_uids) c.conn.expunge()
def test_multisend_session(api_client, multisend, multisend2, patch_smtp, patch_crispin_del_sent, patch_sentry_to_raise): r = api_client.post_data('/send-multiple/' + multisend['id'], multisend['send_req']) assert r.status_code == 200 assert json.loads(r.data)['body'] == multisend['send_req']['body'] r = api_client.post_data('/send-multiple/' + multisend2['id'], multisend2['send_req']) assert r.status_code == 200 assert json.loads(r.data)['body'] == multisend2['send_req']['body'] # Make sure we can't send to people not in the message recipients req_body = { 'send_req': { 'body': "you're not even a recipient!", 'send_to': { 'name': 'not in message', 'email': '*****@*****.**' } } } r = api_client.post_data('/send-multiple/' + multisend['id'], req_body) assert r.status_code == 400 r = api_client.delete('/send-multiple/' + multisend['id']) assert r.status_code == 200 assert json.loads(r.data)['body'] == multisend['draft']['body']
def test_api_list(db, api_client, calendar): e_data = {'title': 'subj', 'description': 'body1', 'calendar_id': calendar.public_id, 'when': {'time': 1}, 'location': 'NylasHQ'} e_data2 = {'title': 'subj2', 'description': 'body2', 'calendar_id': calendar.public_id, 'when': {'time': 1}, 'location': 'NylasHQ'} 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()
def test_quoted_printable_encoding_avoided_for_compatibility( patch_smtp, api_client): # Test that messages with long lines don't get quoted-printable encoded, # for maximum server compatibility. api_client.post_data( '/send', { 'to': [{ 'email': '*****@*****.**' }], 'subject': 'In Catilinam', 'body': 'Etenim quid est, Catilina, quod iam amplius exspectes, si ' 'neque nox tenebris obscurare coeptus nefarios neque privata domus ' 'parietibus continere voces conjurationis tuae potest? Si ' 'illustrantur, si erumpunt omnia? Muta iam istam mentem, mihi crede! ' 'obliviscere caedis atque incendiorum. Teneris undique: luce sunt ' 'clariora nobis tua consilia omnia; quae iam mecum licet recognoscas.' ' Meministine me ante diem duodecimum Kalendas Novembres dicere in ' 'senatu, fore in armis certo die, qui dies futurus esset ante diem ' 'sextum Kalendas Novembres, C. Manlium, audaciae satellitem atque ' 'administrum tuae? Num me fefellit, Catilina, non modo res tanta, tam' ' atrox, tamque incredibilis, verum id quod multo magis admirandum, ' 'dies? ' }) _, msg = patch_smtp[-1] parsed = mime.from_string(msg) assert len(parsed.parts) == 2 for part in parsed.parts: if part.content_type.value == 'text/html': assert part.content_encoding[0] == 'base64' elif part.content_type.value == 'text/plain': assert part.content_encoding[0] in ('7bit', 'base64')
def test_quoted_printable_encoding_avoided_for_compatibility( patch_smtp, api_client): # Test that messages with long lines don't get quoted-printable encoded, # for maximum server compatibility. api_client.post_data( '/send', {'to': [{'email': '*****@*****.**'}], 'subject': 'In Catilinam', 'body': 'Etenim quid est, Catilina, quod iam amplius exspectes, si ' 'neque nox tenebris obscurare coeptus nefarios neque privata domus ' 'parietibus continere voces conjurationis tuae potest? Si ' 'illustrantur, si erumpunt omnia? Muta iam istam mentem, mihi crede! ' 'obliviscere caedis atque incendiorum. Teneris undique: luce sunt ' 'clariora nobis tua consilia omnia; quae iam mecum licet recognoscas.' ' Meministine me ante diem duodecimum Kalendas Novembres dicere in ' 'senatu, fore in armis certo die, qui dies futurus esset ante diem ' 'sextum Kalendas Novembres, C. Manlium, audaciae satellitem atque ' 'administrum tuae? Num me fefellit, Catilina, non modo res tanta, tam' ' atrox, tamque incredibilis, verum id quod multo magis admirandum, ' 'dies? '}) _, msg = patch_smtp[-1] parsed = mime.from_string(msg) assert len(parsed.parts) == 2 for part in parsed.parts: if part.content_type.value == 'text/html': assert part.content_encoding[0] == 'base64' elif part.content_type.value == 'text/plain': assert part.content_encoding[0] in ('7bit', 'base64')
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
def test_send_rejected_with_wrong_version(api_client, example_draft): r = api_client.post_data('/drafts', example_draft) draft_public_id = json.loads(r.data)['id'] r = api_client.post_data('/send', { 'draft_id': draft_public_id, 'version': 222 }) assert r.status_code == 409
def test_send_rejected_without_recipients(api_client): r = api_client.post_data('/drafts', {'subject': 'Hello there'}) 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 == 400
def test_multisend_init_rejected_with_existing_draft(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-multiple', {'draft_id': draft_public_id, 'version': version}) assert r.status_code == 400
def test_draft_not_persisted_if_sending_fails(recipients_refused, api_client, db): api_client.post_data('/send', { 'to': [{ 'email': '*****@*****.**' }], 'subject': 'some unique subject' }) assert db.session.query(Message).filter_by( subject='some unique subject').first() is None
def test_create_event(db, api_client, calendar): e_data = {'title': 'subj', 'description': 'body1', 'calendar_id': calendar.public_id, 'when': {'time': 1}, 'location': 'NylasHQ'} e_data2 = {'title': 'subj2', 'description': 'body2', 'calendar_id': calendar.public_id, 'when': {'time': 1}, 'location': 'NylasHQ'} api_client.post_data('/events', e_data) api_client.post_data('/events', e_data2) db.session.commit()
def test_send_rejected_without_recipients(api_client): r = api_client.post_data('/drafts', {'subject': 'Hello there'}) 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 == 400
def test_multisend_init_rejected_with_existing_draft(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-multiple', { 'draft_id': draft_public_id, 'version': version }) assert r.status_code == 400
def test_sending_from_email_alias(patch_smtp, api_client): api_client.post_data('/send', {'to': [{'email': '*****@*****.**'}], 'from': [{'name': 'admin', 'email': '*****@*****.**'}], 'subject': 'Banalities', 'body': '<html>Hello there</html>'}) _, msg = patch_smtp[-1] parsed = mime.from_string(msg) assert 'From' in parsed.headers assert parsed.headers['From'] == 'admin <*****@*****.**>'
def test_sent_messages_shown_in_delta(patch_smtp, api_client, example_draft): ts = int(time.time()) r = api_client.post_data('/delta/generate_cursor', {'start': ts}) cursor = json.loads(r.data)['cursor'] r = api_client.post_data('/send', example_draft) message_id = json.loads(r.data)['id'] deltas = api_client.get_data('/delta?cursor={}'.format(cursor))['deltas'] message_delta = next((d for d in deltas if d['id'] == message_id), None) assert message_delta is not None assert message_delta['object'] == 'message' assert message_delta['event'] == 'create'
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
def test_invalid_timestamp(api_client, default_namespace): # Valid UNIX timestamp response = api_client.post_data( '/delta/generate_cursor', data={'start': int(time.time())}) assert response.status_code == 200 # Invalid timestamp response = api_client.post_data( '/delta/generate_cursor', data={'start': 1434591487647}) assert response.status_code == 400
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)
def label_client(db, gmail_account): api_client = new_api_client(db, gmail_account.namespace) # Whereas calling generic_account always makes a new IMAP account, # calling gmail_account checks first to see if there's an existing # Gmail account and uses it if so. This can cause namespace # conflicts if a label is "created" more than once. Since # labels can't be deleted and then re-created, this fixture only # makes a new label if there are no existing labels. g_data = api_client.get_raw('/labels/') if not json.loads(g_data.data): api_client.post_data('/labels/', {"display_name": "Test_Label"}) return api_client
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 # Check that contacts aren't created for garbage recipients. r = api_client.post_data('/drafts', {'to': [{ 'name': 'who', 'email': 'nope' }]}) assert r.status_code == 200 r = api_client.get_data('/threads?to=nope') assert len(r) == 0 r = api_client.get_data('/contacts?filter=nope') assert len(r) == 0
def test_delete_draft(api_client, thread, message): 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 len(thread['draft_ids']) > 0 api_client.delete('/drafts/{}'.format(public_id), {'version': version}) thread = api_client.get_data('/threads/{}'.format(thread_public_id)) assert thread assert len(thread['draft_ids']) == 0
def test_rsvp_idempotent(db, patch_smtp, api_client, example_rsvp, imported_event, status, comment): part = imported_event.participants[0] part['status'] = status part['comment'] = comment # MutableList shenanigans -- it won't update # what's stored in the db otherwise. imported_event.participants = [] db.session.commit() imported_event.participants = [part] db.session.commit() old_update_date = imported_event.updated_at db.session.expunge(imported_event) rsvp = {'event_id': imported_event.public_id, 'status': status, 'comment': comment} r = api_client.post_data('/send-rsvp', rsvp) assert r.status_code == 200 dct = json.loads(r.data) # check that the event's status is the same. assert len(dct['participants']) == 1 assert dct['participants'][0]['email'] == '*****@*****.**' assert dct['participants'][0]['status'] == status assert dct['participants'][0]['comment'] == comment # Check that the event hasn't been updated. refreshed_event = db.session.query(Event).get(imported_event.id) assert refreshed_event.updated_at == old_update_date
def test_inline_html_image_send(patch_smtp, api_client, uploaded_file_ids): file_id = uploaded_file_ids[0] r = api_client.post_data( '/send', { 'subject': 'Inline image test', 'body': 'Before image\r\n[cid:{}]\r\nAfter image'.format(file_id), 'body': '<html><body><div></div><img src="cid:{}"><div></div></body></html>' .format(file_id), 'file_ids': [file_id], 'to': [{ 'name': 'Foo Bar', 'email': '*****@*****.**' }] }) assert r.status_code == 200 _, msg = patch_smtp[-1] parsed = mime.from_string(msg) for mimepart in parsed.walk(): if mimepart.headers['Content-Type'] == 'image/jpeg': assert mimepart.headers['Content-Id'] == '<{}>'.format(file_id) assert mimepart.headers['Content-Disposition'][0] == 'inline'
def test_malformed_subject_rejected(api_client, example_draft_bad_subject): r = api_client.post_data('/send', example_draft_bad_subject) assert r.status_code == 400 decoded = json.loads(r.get_data()) assert decoded['type'] == 'invalid_request_error' assert decoded['message'] == '"subject" should be a string'
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
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_multisend_handle_recipients_rejected(recipients_refused, api_client, multisend, patch_crispin_del_sent): r = api_client.post_data('/send-multiple/' + multisend['id'], multisend['send_req']) assert r.status_code == 402 assert json.loads(r.data)['message'] == 'Sending to all recipients failed'
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']
def test_api_pessimistic_update(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, headers={ "Api-Version": API_VERSIONS[1] }) e_resp_data = json.loads(e_resp.data) assert e_resp_data['object'] == 'event' assert e_resp_data['account_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, headers={ "Api-Version": API_VERSIONS[1] }) e_put_data = json.loads(e_put_resp.data) assert e_put_data['object'] == 'event' assert e_put_data['account_id'] == default_account.namespace.public_id assert e_put_data['id'] == e_id assert e_put_data['title'] == '' assert e_put_data['when']['object'] == 'time' assert e_put_data['when']['time'] == e_data['when']['time']
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_attachment_has_same_id(api_client, uploaded_file_ids, draft): attachment_id = uploaded_file_ids.pop() draft['file_ids'] = [attachment_id] r = api_client.post_data('/drafts', draft) assert r.status_code == 200 draft_resp = json.loads(r.data) assert attachment_id in [x['id'] for x in draft_resp['files']]
def test_account_validation(api_client, db, default_namespace): draft = {'body': '<html><body><h2>Sea, birds and sand.</h2></body></html>'} r = api_client.post_data('/drafts', draft) assert r.status_code == 200 namespace_id = json.loads(r.data)['account_id'] account = db.session.query(Namespace).filter( Namespace.public_id == namespace_id).first().account account.sync_state = 'invalid' db.session.commit() r = api_client.post_data('/drafts', draft) assert r.status_code == 403
def test_api_pessimistic_delete(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, headers={"Api-Version": API_VERSIONS[1]}) e_resp_data = json.loads(e_resp.data) assert e_resp_data['object'] == 'event' 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_delete_resp = api_client.delete('/events/' + e_id, headers={"Api-Version": API_VERSIONS[1]}) assert e_delete_resp.status_code == 200 e_resp = api_client.get_data('/events/' + e_id) assert e_resp['status'] == 'confirmed'
def test_api_create_multiple(db, api_client, calendar): e_data = { 'title': 'Friday Office Party', 'when': {'time': 1407542195}, 'calendar_id': calendar.public_id, 'participants': [{ 'email': '*****@*****.**', }, { 'email': '*****@*****.**', }] } e_resp = api_client.post_data('/events', e_data) e_resp_data = json.loads(e_resp.data) assert len(e_resp_data['participants']) == 2 for participant in e_resp_data['participants']: res = [e for e in e_data['participants'] if e['email'] == participant['email']] assert len(res) == 1 participant0 = e_resp_data['participants'][0] participant1 = e_resp_data['participants'][1] assert participant0['name'] is None assert participant0['status'] == 'noreply' assert participant1['name'] is None assert participant1['status'] == 'noreply'
def test_api_create(db, api_client, calendar, default_account): e_data = { 'title': 'Friday Office Party', 'calendar_id': calendar.public_id, 'when': { 'time': 1407542195 }, 'location': 'Nylas HQ', } 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['account_id'] == default_account.namespace.public_id assert e_resp_data['title'] == e_data['title'] assert e_resp_data['location'] == e_data['location'] assert e_resp_data['when']['time'] == e_data['when']['time'] assert 'id' in e_resp_data e_id = e_resp_data['id'] e_get_resp = api_client.get_data('/events/' + e_id) assert e_get_resp['object'] == 'event' assert e_get_resp['account_id'] == default_account.namespace.public_id assert e_get_resp['id'] == e_id assert e_get_resp['title'] == e_data['title'] assert e_get_resp['when']['time'] == e_data['when']['time']
def test_api_pessimistic_update(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, headers={"Api-Version": API_VERSIONS[1]}) e_resp_data = json.loads(e_resp.data) assert e_resp_data['object'] == 'event' assert e_resp_data['account_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, headers={"Api-Version": API_VERSIONS[1]}) e_put_data = json.loads(e_put_resp.data) assert e_put_data['object'] == 'event' assert e_put_data['account_id'] == default_account.namespace.public_id assert e_put_data['id'] == e_id assert e_put_data['title'] == '' assert e_put_data['when']['object'] == 'time' assert e_put_data['when']['time'] == e_data['when']['time']
def test_api_remove_participant(db, api_client, calendar): e_data = { 'title': 'Friday Office Party', 'when': {'time': 1407542195}, 'calendar_id': calendar.public_id, 'participants': [{'email': '*****@*****.**'}, {'email': '*****@*****.**'}, {'email': '*****@*****.**'}, {'email': '*****@*****.**'}, {'email': '*****@*****.**'}] } e_resp = api_client.post_data('/events', e_data) 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) 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_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_multisend_handle_server_disconnected(connection_closed, api_client, multisend, patch_crispin_del_sent): r = api_client.post_data('/send-multiple/' + multisend['id'], multisend['send_req']) assert r.status_code == 503 assert json.loads(r.data)['message'] == 'The server unexpectedly closed ' \ 'the connection'
def test_multisend_message_rejected_for_security(insecure_content, api_client, multisend, patch_crispin_del_sent): r = api_client.post_data('/send-multiple/' + multisend['id'], multisend['send_req']) assert r.status_code == 402 assert json.loads(r.data)['message'] == 'Message content rejected ' \ 'for security reasons'
def test_delete_draft(api_client, thread, message): 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 len(thread['draft_ids']) > 0 api_client.delete('/drafts/{}'.format(public_id), {'version': version}) thread = api_client.get_data('/threads/{}'.format(thread_public_id)) assert thread assert len(thread['draft_ids']) == 0
def test_multisend_handle_invalid_credentials(disallow_auth, api_client, multisend, patch_crispin_del_sent): r = api_client.post_data('/send-multiple/' + multisend['id'], multisend['send_req']) assert r.status_code == 403 assert json.loads(r.data)['message'] == 'Could not authenticate with ' \ 'the SMTP server.'
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
def test_invalid_input(api_client): cursor_response = api_client.post_data('/delta/generate_cursor', {'start': "I'm not a timestamp!"}) assert cursor_response.status_code == 400 sync_response = api_client.client.get( '/delta?cursor={}'.format('fake cursor'), headers=api_client.auth_header) assert sync_response.status_code == 400
def test_multisend_init_malformed_body_rejected(api_client, example_draft_bad_body): r = api_client.post_data('/send-multiple', example_draft_bad_body) assert r.status_code == 400 decoded = json.loads(r.get_data()) assert decoded['type'] == 'invalid_request_error' assert decoded['message'] == '"body" should be a string'