diff --git a/app/v2/inbound_sms/__init__.py b/app/v2/inbound_sms/__init__.py index d48a37f94..5c713b2ef 100644 --- a/app/v2/inbound_sms/__init__.py +++ b/app/v2/inbound_sms/__init__.py @@ -1,6 +1,6 @@ from flask import Blueprint from app.v2.errors import register_errors -v2_inbound_sms_blueprint = Blueprint("v2_inbound_sms", __name__, url_prefix='/v2/inbound_sms') +v2_inbound_sms_blueprint = Blueprint("v2_inbound_sms", __name__, url_prefix='/v2/received-text-messages') register_errors(v2_inbound_sms_blueprint) diff --git a/app/v2/inbound_sms/get_inbound_sms.py b/app/v2/inbound_sms/get_inbound_sms.py index 10ae26885..1ebae90c5 100644 --- a/app/v2/inbound_sms/get_inbound_sms.py +++ b/app/v2/inbound_sms/get_inbound_sms.py @@ -15,22 +15,69 @@ from app.v2.inbound_sms import v2_inbound_sms_blueprint @v2_inbound_sms_blueprint.route("/", methods=['GET']) def get_inbound_sms_by_number(user_number): + _data = request.args.to_dict(flat=False) + + # flat=False makes everything a list, but we only ever allow one value for "older_than" + if 'older_than' in _data: + _data['older_than'] = _data['older_than'][0] + try: - validate_and_format_phone_number(user_number) + user_number = validate_and_format_phone_number(user_number) except InvalidPhoneError as e: raise BadRequestError(message=str(e)) - inbound_sms = inbound_sms_dao.dao_get_inbound_sms_for_service( - authenticated_service.id, user_number=user_number + paginated_inbound_sms = inbound_sms_dao.dao_get_paginated_inbound_sms_for_service( + authenticated_service.id, + user_number=user_number, + older_than=_data.get('older_than'), + page_size=current_app.config.get('API_PAGE_SIZE') ) - return jsonify(inbound_sms_list=[i.serialize() for i in inbound_sms]), 200 + return jsonify( + inbound_sms_list=[i.serialize() for i in paginated_inbound_sms], + links=_build_links( + paginated_inbound_sms, + endpoint='get_inbound_sms_by_number', + user_number=user_number + ) + ), 200 @v2_inbound_sms_blueprint.route("", methods=['GET']) def get_all_inbound_sms(): - all_inbound_sms = inbound_sms_dao.dao_get_inbound_sms_for_service( - authenticated_service.id + _data = request.args.to_dict(flat=False) + + # flat=False makes everything a list, but we only ever allow one value for "older_than" + if 'older_than' in _data: + _data['older_than'] = _data['older_than'][0] + + paginated_inbound_sms = inbound_sms_dao.dao_get_paginated_inbound_sms_for_service( + authenticated_service.id, + older_than=_data.get('older_than'), + page_size=current_app.config.get('API_PAGE_SIZE') ) - return jsonify(inbound_sms_list=[i.serialize() for i in all_inbound_sms]), 200 + return jsonify( + inbound_sms_list=[i.serialize() for i in paginated_inbound_sms], + links=_build_links(paginated_inbound_sms, endpoint='get_all_inbound_sms') + ), 200 + + +def _build_links(inbound_sms_list, endpoint, user_number=None): + _links = { + 'current': url_for( + "v2_inbound_sms.{}".format(endpoint), + user_number=user_number, + _external=True, + ), + } + + if inbound_sms_list: + _links['next'] = url_for( + "v2_inbound_sms.{}".format(endpoint), + user_number=user_number, + older_than=inbound_sms_list[-1].id, + _external=True, + ) + + return _links diff --git a/app/v2/inbound_sms/inbound_sms_schemas.py b/app/v2/inbound_sms/inbound_sms_schemas.py index 8dedda195..0990c1e2e 100644 --- a/app/v2/inbound_sms/inbound_sms_schemas.py +++ b/app/v2/inbound_sms/inbound_sms_schemas.py @@ -43,8 +43,21 @@ get_inbound_sms_response = { "$ref": "#/definitions/inbound_sms" } }, + "links": { + "type": "object", + "properties": { + "current": { + "type": "string" + }, + "next": { + "type": "string" + } + }, + "additionalProperties": False, + "required": ["current"] + } }, - "required": ["inbound_sms_list"], + "required": ["inbound_sms_list", "links"], "definitions": { "inbound_sms": get_inbound_sms_single_response } diff --git a/tests/app/v2/inbound_sms/test_get_inbound_sms.py b/tests/app/v2/inbound_sms/test_get_inbound_sms.py index 028692414..34eb0420a 100644 --- a/tests/app/v2/inbound_sms/test_get_inbound_sms.py +++ b/tests/app/v2/inbound_sms/test_get_inbound_sms.py @@ -14,12 +14,12 @@ def test_get_all_inbound_sms_returns_200( create_inbound_sms(service=sample_service, user_number='447700900111', content='Hi'), create_inbound_sms(service=sample_service, user_number='447700900112'), create_inbound_sms(service=sample_service, user_number='447700900111', content='Bye'), - create_inbound_sms(service=sample_service, user_number='447700900113') + create_inbound_sms(service=sample_service, user_number='07700900113') ] auth_header = create_authorization_header(service_id=sample_service.id) response = client.get( - path='/v2/inbound_sms', + path='/v2/received-text-messages', headers=[('Content-Type', 'application/json'), auth_header]) assert response.status_code == 200 @@ -34,12 +34,47 @@ def test_get_all_inbound_sms_returns_200( assert json_response == expected_response +@pytest.mark.parametrize('inbound_sms_path,user_number', [ + ('v2_inbound_sms.get_all_inbound_sms', None), + ('v2_inbound_sms.get_inbound_sms_by_number', '447700900111') +]) +def test_get_all_inbound_sms_generate_page_links( + client, sample_service, mocker, inbound_sms_path, user_number +): + mocker.patch.dict("app.v2.inbound_sms.get_inbound_sms.current_app.config", {"API_PAGE_SIZE": 1}) + all_inbound_sms = [ + create_inbound_sms(service=sample_service, user_number='447700900111', content='Hi'), + create_inbound_sms(service=sample_service, user_number='447700900111'), + ] + + auth_header = create_authorization_header(service_id=sample_service.id) + response = client.get( + path=url_for(inbound_sms_path, user_number=user_number), + headers=[('Content-Type', 'application/json'), auth_header]) + + assert response.status_code == 200 + + json_response = json.loads(response.get_data(as_text=True)) + expected_inbound_sms_list = [all_inbound_sms[-1].serialize()] + + assert json_response['inbound_sms_list'] == expected_inbound_sms_list + assert url_for( + inbound_sms_path, + user_number=user_number, + _external=True) == json_response['links']['current'] + assert url_for( + inbound_sms_path, + user_number=user_number, + older_than=all_inbound_sms[-1].id, + _external=True) == json_response['links']['next'] + + def test_get_all_inbound_sms_for_no_inbound_sms_returns_200( client, sample_service ): auth_header = create_authorization_header(service_id=sample_service.id) response = client.get( - path='/v2/inbound_sms', + path='/v2/received-text-messages', headers=[('Content-Type', 'application/json'), auth_header]) assert response.status_code == 200 @@ -55,10 +90,13 @@ def test_get_all_inbound_sms_for_no_inbound_sms_returns_200( def test_get_inbound_sms_by_number_returns_200( client, sample_service ): - sample_inbound_sms = create_inbound_sms(service=sample_service) + sample_inbound_sms1 = create_inbound_sms(service=sample_service, user_number='447700900111') + create_inbound_sms(service=sample_service, user_number='447700900112') + sample_inbound_sms2 = create_inbound_sms(service=sample_service, user_number='447700900111') + auth_header = create_authorization_header(service_id=sample_service.id) response = client.get( - path='/v2/inbound_sms/{}'.format(sample_inbound_sms.user_number), + path='/v2/received-text-messages/{}'.format('07700900111'), headers=[('Content-Type', 'application/json'), auth_header]) assert response.status_code == 200 @@ -66,7 +104,7 @@ def test_get_inbound_sms_by_number_returns_200( json_response = json.loads(response.get_data(as_text=True))['inbound_sms_list'] - expected_response = [sample_inbound_sms.serialize()] + expected_response = [sample_inbound_sms2.serialize(), sample_inbound_sms1.serialize()] assert json_response == expected_response @@ -76,7 +114,7 @@ def test_get_inbound_sms_for_no_inbound_sms_returns_200( ): auth_header = create_authorization_header(service_id=sample_service.id) response = client.get( - path='/v2/inbound_sms', + path='/v2/received-text-messages', headers=[('Content-Type', 'application/json'), auth_header]) assert response.status_code == 200 @@ -92,7 +130,7 @@ def test_get_inbound_sms_for_no_inbound_sms_returns_200( def test_get_inbound_sms_by_nonexistent_number(client, sample_service): auth_header = create_authorization_header(service_id=sample_service.id) response = client.get( - path='/v2/inbound_sms/447700900000', + path='/v2/received-text-messages/447700900000', headers=[('Content-Type', 'application/json'), auth_header]) assert response.status_code == 200 @@ -113,7 +151,7 @@ def test_get_inbound_sms_by_invalid_number( client, sample_service, invalid_number, expected_message): auth_header = create_authorization_header(service_id=sample_service.id) response = client.get( - path='/v2/inbound_sms/{}'.format(invalid_number), + path='/v2/received-text-messages/{}'.format(invalid_number), headers=[('Content-Type', 'application/json'), auth_header]) assert response.status_code == 400 diff --git a/tests/app/v2/inbound_sms/test_inbound_sms_schemas.py b/tests/app/v2/inbound_sms/test_inbound_sms_schemas.py index 9a7f654ba..6365d90a5 100644 --- a/tests/app/v2/inbound_sms/test_inbound_sms_schemas.py +++ b/tests/app/v2/inbound_sms/test_inbound_sms_schemas.py @@ -20,7 +20,11 @@ valid_inbound_sms = { } valid_inbound_sms_list = { - "inbound_sms_list": [valid_inbound_sms] + "inbound_sms_list": [valid_inbound_sms], + "links": { + "current": valid_inbound_sms["id"] + } + } invalid_inbound_sms = { @@ -40,7 +44,7 @@ invalid_inbound_sms_list = { def test_get_inbound_sms_contract(client, sample_inbound_sms): auth_header = create_authorization_header(service_id=sample_inbound_sms.service_id) - response = client.get('/v2/inbound_sms/{}'.format(sample_inbound_sms.user_number), headers=[auth_header]) + response = client.get('/v2/received-text-messages/{}'.format(sample_inbound_sms.user_number), headers=[auth_header]) response_json = json.loads(response.get_data(as_text=True)) assert validate(response_json, get_inbound_sms_response)['inbound_sms_list'][0] \