def test_send_message(fake_app, recipients, sys_msg, resp, err): """ The send message function is able to generate system messages by prepending the message with the organization name. It can broadcast the message to multiple recipients. If an error occurs when using the SMS controller client, an internal exception is raised, bubbles up and is tranformed to a response for the client side. Database state is not rolled back in the event of a message send failure. """ session_id = 'session_id' msg = 'hello' virtual_tn = '13334445555' from sms_proxy.api import send_message if resp is False: fake_app.sms_controller.resp.append(resp) with pytest.raises(err): send_message(recipients, virtual_tn, msg, session_id, is_system_msg=sys_msg) else: send_message(recipients, virtual_tn, msg, session_id, is_system_msg=sys_msg) assert len(fake_app.sms_controller.requests) == len(recipients) if sys_msg: msg = "[{}]: {}".format(ORG_NAME.upper(), msg) for sms in fake_app.sms_controller.requests: assert sms.to in recipients assert sms.mfrom == virtual_tn assert sms.content == msg
def send_message(recipients, virtual_tn, msg, session_id, is_system_msg=False): """ For each recipient, passes a Message to Flowroute's messaging controller. The message will be sent from the 'virtual_tn' number. If this is a system message, the message body will be prefixed with the org name for context. If an exception is raised by the controller, an error is logged, and an internal error is raised with the exception content. """ if is_system_msg: msg = "[{}]: {}".format(ORG_NAME.upper(), msg) for recipient in recipients: message = Message(to=recipient, from_=virtual_tn, content=msg) try: app.sms_controller.create_message(message) except Exception as e: strerr = vars(e).get("response_body", None) log.critical( { "message": "Raised an exception sending SMS", "status": "failed", "exc": e, "strerr": vars(e).get("response_body", None), } ) raise InternalSMSDispatcherError( "An error occured when requesting against Flowroute's API.", payload={"strerr": strerr, "reason": "InternalSMSDispatcherError"}, ) else: log.info( {"message": "Message sent to {} for session {}".format(recipient, session_id), "status": "succeeded"} )
def test_inbound_handler_expired_session(fake_app, valid_session): """ An inbound message intended for a VirtualTN that is no longer in a session with the sender will no proxy to the other participant. Asserts a system message is fired back to the sender. """ valid_session.expiry_date = datetime.utcnow() db_session.add(valid_session) db_session.commit() expired_session = valid_session client = fake_app.test_client() req = { 'to': expired_session.virtual_TN, 'from': expired_session.participant_a, 'body': 'hello from participant a' } resp = client.post('/', data=json.dumps(req), content_type='application/json') # Indicating that we received the message from Flowroute assert resp.status_code == 200 sms = fake_app.sms_controller.requests[0] msg = "[{}]: {}".format(ORG_NAME.upper(), NO_SESSION_MSG) assert sms.content == msg assert sms.to == expired_session.participant_a assert sms.mfrom == expired_session.virtual_TN
def test_post_session(): """ Initially attempts to create a session when there are no VirtualTN's available. The service responds with a 400, and an appropriate message. Attempts again, when there is a VirtualTN in the pool, but reserved, the service will respond again with a 400. After releasing the VirtualTN, the request succesfully posts, and the response is checked for appropriate values. Ensures both session initialization SMS messages have been fired off. """ mock_controller = MockController() app.sms_controller = mock_controller client = app.test_client() test_num = '12223334444' resp = client.post('/session', data=json.dumps({ 'participant_a': '13334445555', 'participant_b': '14445556666' }), content_type='application/json') data = json.loads(resp.data) assert resp.status_code == 400 assert 'Could not create a new session -- No virtual TNs available.' in data[ 'message'] vnum = VirtualTN(test_num) vnum.session_id = 'fake_session_id' db_session.add(vnum) db_session.commit() resp = client.post('/session', data=json.dumps({ 'participant_a': '13334445555', 'participant_b': '14445556666' }), content_type='application/json') data = json.loads(resp.data) assert resp.status_code == 400 vnum.session_id = None db_session.add(vnum) db_session.commit() resp = client.post('/session', data=json.dumps({ 'participant_a': '13334445555', 'participant_b': '14445556666' }), content_type='application/json') assert resp.status_code == 200 data = json.loads(resp.data) assert 'Created new session' in data['message'] assert data['virtual_tn'] == vnum.value assert len(mock_controller.requests) == 2 msg = "[{}]: {}".format(ORG_NAME.upper(), SESSION_START_MSG) sms = mock_controller.requests[0] assert sms.content == msg assert data['session_id'] is not None
def test_post_session(): """ Initially attempts to create a session when there are no VirtualTN's available. The service responds with a 400, and an appropriate message. Attempts again, when there is a VirtualTN in the pool, but reserved, the service will respond again with a 400. After releasing the VirtualTN, the request succesfully posts, and the response is checked for appropriate values. Ensures both session initialization SMS messages have been fired off. """ mock_controller = MockController() app.sms_controller = mock_controller client = app.test_client() test_num = '12223334444' resp = client.post('/session', data=json.dumps({'participant_a': '13334445555', 'participant_b': '14445556666'}), content_type='application/json') data = json.loads(resp.data) assert resp.status_code == 400 assert 'Could not create a new session -- No virtual TNs available.' in data['message'] vnum = VirtualTN(test_num) vnum.session_id = 'fake_session_id' db_session.add(vnum) db_session.commit() resp = client.post('/session', data=json.dumps({'participant_a': '13334445555', 'participant_b': '14445556666'}), content_type='application/json') data = json.loads(resp.data) assert resp.status_code == 400 vnum.session_id = None db_session.add(vnum) db_session.commit() resp = client.post('/session', data=json.dumps({'participant_a': '13334445555', 'participant_b': '14445556666'}), content_type='application/json') assert resp.status_code == 200 data = json.loads(resp.data) assert 'Created new session' in data['message'] assert data['virtual_tn'] == vnum.value assert len(mock_controller.requests) == 2 msg = "[{}]: {}".format(ORG_NAME.upper(), SESSION_START_MSG) sms = mock_controller.requests[0] assert sms.content == msg assert data['session_id'] is not None
def test_delete_session(): """ Initially tries to delete a session from an id that is unknown. The service responds with a 404, and helpful message. A session is created an persisted to the database. A delete request for that session is executed, and SMS's are dispatched to the participants. """ mock_controller = MockController() app.sms_controller = mock_controller client = app.test_client() resp = client.delete('/session', data=json.dumps({'session_id': 'fake_id'}), content_type='application/json') data = json.loads(resp.data) assert resp.status_code == 404 msg = ("ProxySession {} could not be deleted because" " it does not exist".format('fake_id')) assert data['message'] == msg test_num_1 = '12223334444' vnum_1 = VirtualTN(test_num_1) sess_1 = ProxySession(test_num_1, 'cust_1_num', 'cust_2_num') vnum_1.session_id = sess_1.id db_session.add(sess_1) db_session.add(vnum_1) db_session.commit() resp = client.delete('/session', data=json.dumps({'session_id': sess_1.id}), content_type='application/json') assert resp.status_code == 200 data = json.loads(resp.data) assert data['message'] == 'Successfully ended the session.' assert data['session_id'] == sess_1.id sms = mock_controller.requests[0] msg = "[{}]: {}".format(ORG_NAME.upper(), SESSION_END_MSG) assert sms.content == msg assert len(mock_controller.requests) == 2
def send_message(recipients, virtual_tn, msg, session_id, is_system_msg=False): """ For each recipient, passes a Message to Flowroute's messaging controller. The message will be sent from the 'virtual_tn' number. If this is a system message, the message body will be prefixed with the org name for context. If an exception is raised by the controller, an error is logged, and an internal error is raised with the exception content. """ if is_system_msg: msg = "[{}]: {}".format(ORG_NAME.upper(), msg) for recipient in recipients: message = Message(to=recipient, from_=virtual_tn, content=msg) try: app.sms_controller.create_message(message) except Exception as e: strerr = vars(e).get('response_body', None) log.critical({ "message": "Raised an exception sending SMS", "status": "failed", "exc": e, "strerr": vars(e).get('response_body', None) }) raise InternalSMSDispatcherError( "An error occured when requesting against Flowroute's API.", payload={ "strerr": strerr, "reason": "InternalSMSDispatcherError" }) else: log.info({ "message": "Message sent to {} for session {}".format( recipient, session_id), "status": "succeeded" })
def test_inbound_handler_expired_session(fake_app, valid_session): """ An inbound message intended for a VirtualTN that is no longer in a session with the sender will no proxy to the other participant. Asserts a system message is fired back to the sender. """ valid_session.expiry_date = datetime.utcnow() db_session.add(valid_session) db_session.commit() expired_session = valid_session client = fake_app.test_client() req = {'to': expired_session.virtual_TN, 'from': expired_session.participant_a, 'body': 'hello from participant a'} resp = client.post('/', data=json.dumps(req), content_type='application/json') # Indicating that we received the message from Flowroute assert resp.status_code == 200 sms = fake_app.sms_controller.requests[0] msg = "[{}]: {}".format(ORG_NAME.upper(), NO_SESSION_MSG) assert sms.content == msg assert sms.to == expired_session.participant_a assert sms.mfrom == expired_session.virtual_TN