From fa3d4413e7df77cdca7228e18325d0e8efd0bbc3 Mon Sep 17 00:00:00 2001 From: Leo Hemsted Date: Tue, 30 Aug 2016 10:41:23 +0100 Subject: [PATCH 1/9] update test requirements requirements should be kept up to date to ensure we get bug fixes and new features as they come - particularly py.test, which we were running an 18 month old version for, and missing out on some useful xfail and fixture enhancements, among other things --- requirements_for_test.txt | 17 ++++++++--------- tests/conftest.py | 6 ++++++ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/requirements_for_test.txt b/requirements_for_test.txt index 1ea6f7a8d..52f1665aa 100644 --- a/requirements_for_test.txt +++ b/requirements_for_test.txt @@ -1,11 +1,10 @@ -r requirements.txt -pep8==1.5.7 -pytest==2.8.3 -pytest-mock==0.8.1 -pytest-cov==2.2.0 +pep8==1.7.0 +pytest==3.0.1 +pytest-mock==1.2 +pytest-cov==2.3.1 coveralls==1.1 -mock==1.0.1 -moto==0.4.19 -flex==5.7.0 -freezegun==0.3.6 -requests-mock==0.7.0 +moto==0.4.25 +flex==5.8.0 +freezegun==0.3.7 +requests-mock==1.0.0 diff --git a/tests/conftest.py b/tests/conftest.py index cf1789d6e..122f4933b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -24,6 +24,12 @@ def notify_api(request): return app +@pytest.yield_fixture(scope='function') +def client(notify_api): + with notify_api.test_request_context(), notify_api.test_client() as client: + yield client + + @pytest.fixture(scope='session') def notify_db(notify_api, request): Migrate(notify_api, db) From 59346d7546343f70047a736634305176037cdd59 Mon Sep 17 00:00:00 2001 From: Leo Hemsted Date: Tue, 30 Aug 2016 11:18:30 +0100 Subject: [PATCH 2/9] add new client fixture replaces previous notify_api fixture with the age old: ``` with notify_api.test_request_context(): with notify_api.test_client() as client: ``` just runs those two context managers in a yield fixture (new pytest 3.0 feature) --- tests/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index 122f4933b..c5c57ae7e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -24,7 +24,7 @@ def notify_api(request): return app -@pytest.yield_fixture(scope='function') +@pytest.fixture(scope='function') def client(notify_api): with notify_api.test_request_context(), notify_api.test_client() as client: yield client From b21c8de9a398d50bf062d6ce05422f8cb48df9fb Mon Sep 17 00:00:00 2001 From: Leo Hemsted Date: Tue, 30 Aug 2016 15:51:56 +0100 Subject: [PATCH 3/9] add new sample_email_notification fixture dont include any of the parameters for now - only add em when we have an actual need for them --- tests/app/conftest.py | 46 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/tests/app/conftest.py b/tests/app/conftest.py index a14dbb5fc..c3d2389d3 100644 --- a/tests/app/conftest.py +++ b/tests/app/conftest.py @@ -1,8 +1,8 @@ -import requests_mock -import pytest import uuid from datetime import (datetime, date) +import requests_mock +import pytest from flask import current_app from app import db @@ -28,7 +28,6 @@ from app.dao.jobs_dao import dao_create_job from app.dao.notifications_dao import dao_create_notification from app.dao.invited_user_dao import save_invited_user from app.clients.sms.firetext import FiretextClient -from app.clients.sms.mmg import MMGClient @pytest.yield_fixture @@ -272,9 +271,9 @@ def sample_job(notify_db, @pytest.fixture(scope='function') def sample_job_with_placeholdered_template( - notify_db, - notify_db_session, - service=None + notify_db, + notify_db_session, + service=None ): return sample_job( notify_db, @@ -370,6 +369,41 @@ def sample_notification(notify_db, return notification +@pytest.fixture(scope='function') +def sample_email_notification(notify_db, notify_db_session): + created_at = datetime.utcnow() + service = sample_service(notify_db, notify_db_session) + template = sample_email_template(notify_db, notify_db_session, service=service) + job = sample_job(notify_db, notify_db_session, service=service, template=template) + + notification_id = uuid.uuid4() + + to = 'foo@bar.com' + + data = { + 'id': notification_id, + 'to': to, + 'job_id': job.id, + 'job': job, + 'service_id': service.id, + 'service': service, + 'template': template, + 'template_version': template.version, + 'status': 'created', + 'reference': None, + 'created_at': created_at, + 'billable_units': 0, + 'personalisation': None, + 'notification_type': template.template_type, + 'api_key_id': None, + 'key_type': KEY_TYPE_NORMAL, + 'job_row_number': 1 + } + notification = Notification(**data) + dao_create_notification(notification) + return notification + + @pytest.fixture(scope='function') def mock_statsd_inc(mocker): return mocker.patch('app.statsd_client.incr') From aebaea1072c9a1345667d2587287584cb57d6f7b Mon Sep 17 00:00:00 2001 From: Leo Hemsted Date: Tue, 30 Aug 2016 15:54:22 +0100 Subject: [PATCH 4/9] add public contract tests use jsonschema to test the GET /notification/{} endpoint to highlight any key name/format/type changes --- requirements_for_test.txt | 2 + tests/app/notifications/test_rest.py | 38 ------ .../GET_notification_return_email.json | 128 ++++++++++++++++++ .../GET_notification_return_sms.json | 127 +++++++++++++++++ tests/app/public_contracts/__init__.py | 0 .../public_contracts/test_GET_notification.py | 30 ++++ 6 files changed, 287 insertions(+), 38 deletions(-) create mode 100644 tests/app/public_contracts/GET_notification_return_email.json create mode 100644 tests/app/public_contracts/GET_notification_return_sms.json create mode 100644 tests/app/public_contracts/__init__.py create mode 100644 tests/app/public_contracts/test_GET_notification.py diff --git a/requirements_for_test.txt b/requirements_for_test.txt index 52f1665aa..e7ded4dff 100644 --- a/requirements_for_test.txt +++ b/requirements_for_test.txt @@ -8,3 +8,5 @@ moto==0.4.25 flex==5.8.0 freezegun==0.3.7 requests-mock==1.0.0 +jsonschema==2.5.1 +strict-rfc3339==0.7 diff --git a/tests/app/notifications/test_rest.py b/tests/app/notifications/test_rest.py index 778bbe66e..f30659f56 100644 --- a/tests/app/notifications/test_rest.py +++ b/tests/app/notifications/test_rest.py @@ -625,44 +625,6 @@ def test_get_notifications_for_service_returns_merged_template_content(notify_ap } -def test_get_notification_public_api_format_is_not_changed(notify_api, sample_notification): - with notify_api.test_request_context(), notify_api.test_client() as client: - auth_header = create_authorization_header(service_id=sample_notification.service_id) - - response = client.get( - '/notifications/{}'.format(sample_notification.id), - headers=[auth_header]) - - assert response.status_code == 200 - notification = json.loads(response.get_data(as_text=True))['data']['notification'] - # you should never remove things from this list! - assert set(notification.keys()) == { - # straight from db - 'id', - 'to', - 'job_row_number', - 'template_version', - 'billable_units', - 'notification_type', - 'created_at', - 'sent_at', - 'sent_by', - 'updated_at', - 'status', - 'reference', - - # relationships - 'template', - 'service', - 'job', - 'api_key', - - # other - 'body', - 'content_char_count' - } - - def test_get_notification_selects_correct_template_for_personalisation(notify_api, notify_db, notify_db_session, diff --git a/tests/app/public_contracts/GET_notification_return_email.json b/tests/app/public_contracts/GET_notification_return_email.json new file mode 100644 index 000000000..78318cdaa --- /dev/null +++ b/tests/app/public_contracts/GET_notification_return_email.json @@ -0,0 +1,128 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "GET notification return schema - for SMS notifications", + "type" : "object", + "properties": { + "data": { + "type": "object", + "properties": { + "notification": { + "type": "object", + "properties": { + "id": {"$ref": "#/definitions/uuid"}, + "to": {"type": "string", "format": "email"}, + "job_row_number": {"oneOf":[ + {"type": "number"}, + {"type": "null"} + ]}, + "template_version": {"type": "number"}, + "billable_units": {"type": "number"}, + "notification_type": { + "type": "string", + "enum": ["email"] + }, + "created_at": {"$ref": "#/definitions/datetime"}, + "sent_at": {"oneOf":[ + {"$ref": "#/definitions/datetime"}, + {"type": "null"} + ]}, + "sent_by": {"oneOf":[ + {"type": "string"}, + {"type": "null"} + ]}, + "updated_at": {"oneOf":[ + {"$ref": "#/definitions/datetime"}, + {"type": "null"} + ]}, + "status": { + "type": "string", + "enum": [ + "created", + "sending", + "delivered", + "pending", + "failed", + "technical-failure", + "temporary-failure", + "permanent-failure" + ] + }, + "reference": {"oneOf":[ + {"type": "string"}, + {"type": "null"} + ]}, + "template": { + "type": "object", + "properties": { + "id": {"$ref": "#/definitions/uuid"}, + "name": {"type": "string"}, + "template_type": { + "type": "string", + "enum": ["email"] + }, + "version": {"type": "number"} + }, + "additionalProperties": false, + "required": ["id", "name", "template_type", "version"] + }, + "service": {"$ref": "#/definitions/uuid"}, + "job": { + "oneOf": [ + { + "type": "object", + "properties": { + "id": {"$ref": "#/definitions/uuid"}, + "original_file_name": {"type": "string"} + }, + "additionalProperties": false, + "required": ["id", "original_file_name"] + }, + {"type": "null"} + ] + }, + "api_key": {"oneOf":[ + {"$ref": "#/definitions/uuid"}, + {"type": "null"} + ]}, + "body": {"type": "string"}, + "content_char_count": {"type": "null"}, + "subject": {"type": "string"} + }, + "additionalProperties": false, + "required": [ + "id", + "to", + "job_row_number", + "template_version", + "billable_units", + "notification_type", + "created_at", + "sent_at", + "sent_by", + "updated_at", + "status", + "reference", + "template", + "service", + "job", + "api_key", + "body", + "content_char_count" + ] + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false, + "definitions": { + "uuid": { + "type": "string", + "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$" + }, + "datetime": { + "type": "string", + "format": "date-time" + } + } +} diff --git a/tests/app/public_contracts/GET_notification_return_sms.json b/tests/app/public_contracts/GET_notification_return_sms.json new file mode 100644 index 000000000..804b91722 --- /dev/null +++ b/tests/app/public_contracts/GET_notification_return_sms.json @@ -0,0 +1,127 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "GET notification return schema - for SMS notifications", + "type" : "object", + "properties": { + "data": { + "type": "object", + "properties": { + "notification": { + "type": "object", + "properties": { + "id": {"$ref": "#/definitions/uuid"}, + "to": {"type": "string"}, + "job_row_number": {"oneOf":[ + {"type": "number"}, + {"type": "null"} + ]}, + "template_version": {"type": "number"}, + "billable_units": {"type": "number"}, + "notification_type": { + "type": "string", + "enum": ["sms"] + }, + "created_at": {"$ref": "#/definitions/datetime"}, + "sent_at": {"oneOf":[ + {"$ref": "#/definitions/datetime"}, + {"type": "null"} + ]}, + "sent_by": {"oneOf":[ + {"type": "string"}, + {"type": "null"} + ]}, + "updated_at": {"oneOf":[ + {"$ref": "#/definitions/datetime"}, + {"type": "null"} + ]}, + "status": { + "type": "string", + "enum": [ + "created", + "sending", + "delivered", + "pending", + "failed", + "technical-failure", + "temporary-failure", + "permanent-failure" + ] + }, + "reference": {"oneOf":[ + {"type": "string"}, + {"type": "null"} + ]}, + "template": { + "type": "object", + "properties": { + "id": {"$ref": "#/definitions/uuid"}, + "name": {"type": "string"}, + "template_type": { + "type": "string", + "enum": ["sms"] + }, + "version": {"type": "number"} + }, + "additionalProperties": false, + "required": ["id", "name", "template_type", "version"] + }, + "service": {"$ref": "#/definitions/uuid"}, + "job": { + "oneOf": [ + { + "type": "object", + "properties": { + "id": {"$ref": "#/definitions/uuid"}, + "original_file_name": {"type": "string"} + }, + "additionalProperties": false, + "required": ["id", "original_file_name"] + }, + {"type": "null"} + ] + }, + "api_key": {"oneOf":[ + {"$ref": "#/definitions/uuid"}, + {"type": "null"} + ]}, + "body": {"type": "string"}, + "content_char_count": {"type": "number"} + }, + "additionalProperties": false, + "required": [ + "id", + "to", + "job_row_number", + "template_version", + "billable_units", + "notification_type", + "created_at", + "sent_at", + "sent_by", + "updated_at", + "status", + "reference", + "template", + "service", + "job", + "api_key", + "body", + "content_char_count" + ] + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false, + "definitions": { + "uuid": { + "type": "string", + "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$" + }, + "datetime": { + "type": "string", + "format": "date-time" + } + } +} diff --git a/tests/app/public_contracts/__init__.py b/tests/app/public_contracts/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/app/public_contracts/test_GET_notification.py b/tests/app/public_contracts/test_GET_notification.py new file mode 100644 index 000000000..d048e34e2 --- /dev/null +++ b/tests/app/public_contracts/test_GET_notification.py @@ -0,0 +1,30 @@ +import os + +from flask import json +import jsonschema + +from tests import create_authorization_header + + +def test_get_sms_contract(client, sample_notification): + auth_header = create_authorization_header(service_id=sample_notification.service_id) + response = client.get('/notifications/{}'.format(sample_notification.id), headers=[auth_header]) + + with open(os.path.join(os.path.dirname(__file__), './GET_notification_return_sms.json')) as schema: + jsonschema.validate( + json.loads(response.get_data(as_text=True)), + json.load(schema), + format_checker=jsonschema.FormatChecker() + ) + + +def test_get_email_contract(client, sample_email_notification): + auth_header = create_authorization_header(service_id=sample_email_notification.service_id) + response = client.get('/notifications/{}'.format(sample_email_notification.id), headers=[auth_header]) + + with open(os.path.join(os.path.dirname(__file__), './GET_notification_return_email.json')) as schema: + jsonschema.validate( + json.loads(response.get_data(as_text=True)), + json.load(schema), + format_checker=jsonschema.FormatChecker() + ) From 1b7b4a2ccb0e756736254dd738db65dc73884f03 Mon Sep 17 00:00:00 2001 From: Leo Hemsted Date: Tue, 30 Aug 2016 18:45:54 +0100 Subject: [PATCH 5/9] separate definitions into separate files to allow reuse see https://github.com/Julian/jsonschema/issues/98 took boring generic things (eg uuid) into definitions.json, and also separated email and sms notification objects into respective files --- .../GET_notification_return_email.json | 119 +----------------- .../GET_notification_return_sms.json | 118 +---------------- tests/app/public_contracts/definitions.json | 12 ++ .../public_contracts/email_notification.json | 108 ++++++++++++++++ .../public_contracts/sms_notification.json | 106 ++++++++++++++++ .../public_contracts/test_GET_notification.py | 23 ++-- 6 files changed, 243 insertions(+), 243 deletions(-) create mode 100644 tests/app/public_contracts/definitions.json create mode 100644 tests/app/public_contracts/email_notification.json create mode 100644 tests/app/public_contracts/sms_notification.json diff --git a/tests/app/public_contracts/GET_notification_return_email.json b/tests/app/public_contracts/GET_notification_return_email.json index 78318cdaa..949033e6b 100644 --- a/tests/app/public_contracts/GET_notification_return_email.json +++ b/tests/app/public_contracts/GET_notification_return_email.json @@ -1,128 +1,15 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "description": "GET notification return schema - for SMS notifications", + "description": "GET notification return schema - for email notifications", "type" : "object", "properties": { "data": { "type": "object", "properties": { - "notification": { - "type": "object", - "properties": { - "id": {"$ref": "#/definitions/uuid"}, - "to": {"type": "string", "format": "email"}, - "job_row_number": {"oneOf":[ - {"type": "number"}, - {"type": "null"} - ]}, - "template_version": {"type": "number"}, - "billable_units": {"type": "number"}, - "notification_type": { - "type": "string", - "enum": ["email"] - }, - "created_at": {"$ref": "#/definitions/datetime"}, - "sent_at": {"oneOf":[ - {"$ref": "#/definitions/datetime"}, - {"type": "null"} - ]}, - "sent_by": {"oneOf":[ - {"type": "string"}, - {"type": "null"} - ]}, - "updated_at": {"oneOf":[ - {"$ref": "#/definitions/datetime"}, - {"type": "null"} - ]}, - "status": { - "type": "string", - "enum": [ - "created", - "sending", - "delivered", - "pending", - "failed", - "technical-failure", - "temporary-failure", - "permanent-failure" - ] - }, - "reference": {"oneOf":[ - {"type": "string"}, - {"type": "null"} - ]}, - "template": { - "type": "object", - "properties": { - "id": {"$ref": "#/definitions/uuid"}, - "name": {"type": "string"}, - "template_type": { - "type": "string", - "enum": ["email"] - }, - "version": {"type": "number"} - }, - "additionalProperties": false, - "required": ["id", "name", "template_type", "version"] - }, - "service": {"$ref": "#/definitions/uuid"}, - "job": { - "oneOf": [ - { - "type": "object", - "properties": { - "id": {"$ref": "#/definitions/uuid"}, - "original_file_name": {"type": "string"} - }, - "additionalProperties": false, - "required": ["id", "original_file_name"] - }, - {"type": "null"} - ] - }, - "api_key": {"oneOf":[ - {"$ref": "#/definitions/uuid"}, - {"type": "null"} - ]}, - "body": {"type": "string"}, - "content_char_count": {"type": "null"}, - "subject": {"type": "string"} - }, - "additionalProperties": false, - "required": [ - "id", - "to", - "job_row_number", - "template_version", - "billable_units", - "notification_type", - "created_at", - "sent_at", - "sent_by", - "updated_at", - "status", - "reference", - "template", - "service", - "job", - "api_key", - "body", - "content_char_count" - ] - } + "notification": {"$ref": "email_notification.json"} }, "additionalProperties": false } }, - "additionalProperties": false, - "definitions": { - "uuid": { - "type": "string", - "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$" - }, - "datetime": { - "type": "string", - "format": "date-time" - } - } + "additionalProperties": false } diff --git a/tests/app/public_contracts/GET_notification_return_sms.json b/tests/app/public_contracts/GET_notification_return_sms.json index 804b91722..356428fde 100644 --- a/tests/app/public_contracts/GET_notification_return_sms.json +++ b/tests/app/public_contracts/GET_notification_return_sms.json @@ -1,127 +1,15 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "description": "GET notification return schema - for SMS notifications", + "description": "GET notification return schema - for sms notifications", "type" : "object", "properties": { "data": { "type": "object", "properties": { - "notification": { - "type": "object", - "properties": { - "id": {"$ref": "#/definitions/uuid"}, - "to": {"type": "string"}, - "job_row_number": {"oneOf":[ - {"type": "number"}, - {"type": "null"} - ]}, - "template_version": {"type": "number"}, - "billable_units": {"type": "number"}, - "notification_type": { - "type": "string", - "enum": ["sms"] - }, - "created_at": {"$ref": "#/definitions/datetime"}, - "sent_at": {"oneOf":[ - {"$ref": "#/definitions/datetime"}, - {"type": "null"} - ]}, - "sent_by": {"oneOf":[ - {"type": "string"}, - {"type": "null"} - ]}, - "updated_at": {"oneOf":[ - {"$ref": "#/definitions/datetime"}, - {"type": "null"} - ]}, - "status": { - "type": "string", - "enum": [ - "created", - "sending", - "delivered", - "pending", - "failed", - "technical-failure", - "temporary-failure", - "permanent-failure" - ] - }, - "reference": {"oneOf":[ - {"type": "string"}, - {"type": "null"} - ]}, - "template": { - "type": "object", - "properties": { - "id": {"$ref": "#/definitions/uuid"}, - "name": {"type": "string"}, - "template_type": { - "type": "string", - "enum": ["sms"] - }, - "version": {"type": "number"} - }, - "additionalProperties": false, - "required": ["id", "name", "template_type", "version"] - }, - "service": {"$ref": "#/definitions/uuid"}, - "job": { - "oneOf": [ - { - "type": "object", - "properties": { - "id": {"$ref": "#/definitions/uuid"}, - "original_file_name": {"type": "string"} - }, - "additionalProperties": false, - "required": ["id", "original_file_name"] - }, - {"type": "null"} - ] - }, - "api_key": {"oneOf":[ - {"$ref": "#/definitions/uuid"}, - {"type": "null"} - ]}, - "body": {"type": "string"}, - "content_char_count": {"type": "number"} - }, - "additionalProperties": false, - "required": [ - "id", - "to", - "job_row_number", - "template_version", - "billable_units", - "notification_type", - "created_at", - "sent_at", - "sent_by", - "updated_at", - "status", - "reference", - "template", - "service", - "job", - "api_key", - "body", - "content_char_count" - ] - } + "notification": {"$ref": "sms_notification.json"} }, "additionalProperties": false } }, - "additionalProperties": false, - "definitions": { - "uuid": { - "type": "string", - "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$" - }, - "datetime": { - "type": "string", - "format": "date-time" - } - } + "additionalProperties": false } diff --git a/tests/app/public_contracts/definitions.json b/tests/app/public_contracts/definitions.json new file mode 100644 index 000000000..d8a2ea3ef --- /dev/null +++ b/tests/app/public_contracts/definitions.json @@ -0,0 +1,12 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "Common definitions - usage example: {'$ref': 'definitions.json#/uuid'} (swap quotes for double quotes)", + "uuid": { + "type": "string", + "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$" + }, + "datetime": { + "type": "string", + "format": "date-time" + }, +} diff --git a/tests/app/public_contracts/email_notification.json b/tests/app/public_contracts/email_notification.json new file mode 100644 index 000000000..6de386eea --- /dev/null +++ b/tests/app/public_contracts/email_notification.json @@ -0,0 +1,108 @@ +{ + "email_notification": { + "description": "Single email notification schema - as returned by GET /notification and GET /notification/{}", + "type": "object", + "properties": { + "id": {"$ref": "definitions.json#/uuid"}, + "to": {"type": "string", "format": "email"}, + "job_row_number": {"oneOf":[ + {"type": "number"}, + {"type": "null"} + ]}, + "template_version": {"type": "number"}, + "billable_units": {"type": "number"}, + "notification_type": { + "type": "string", + "enum": ["email"] + }, + "created_at": {"$ref": "definitions.json#/datetime"}, + "sent_at": {"oneOf":[ + {"$ref": "definitions.json#/datetime"}, + {"type": "null"} + ]}, + "sent_by": {"oneOf":[ + {"type": "string"}, + {"type": "null"} + ]}, + "updated_at": {"oneOf":[ + {"$ref": "definitions.json#/datetime"}, + {"type": "null"} + ]}, + "status": { + "type": "string", + "enum": [ + "created", + "sending", + "delivered", + "pending", + "failed", + "technical-failure", + "temporary-failure", + "permanent-failure" + ] + }, + "reference": {"oneOf":[ + {"type": "string"}, + {"type": "null"} + ]}, + "template": { + "type": "object", + "properties": { + "id": {"$ref": "definitions.json#/uuid"}, + "name": {"type": "string"}, + "template_type": { + "type": "string", + "enum": ["email"] + }, + "version": {"type": "number"} + }, + "additionalProperties": false, + "required": ["id", "name", "template_type", "version"] + }, + "service": {"$ref": "definitions.json#/uuid"}, + "job": { + "oneOf": [ + { + "type": "object", + "properties": { + "id": {"$ref": "definitions.json#/uuid"}, + "original_file_name": {"type": "string"} + }, + "additionalProperties": false, + "required": ["id", "original_file_name"] + }, + {"type": "null"} + ] + }, + "api_key": {"oneOf":[ + {"$ref": "definitions.json#/uuid"}, + {"type": "null"} + ]}, + "body": {"type": "string"}, + "content_char_count": {"type": "null"}, + "subject": {"type": "string"} + }, + "additionalProperties": false, + "required": [ + "id", + "to", + "job_row_number", + "template_version", + "billable_units", + "notification_type", + "created_at", + "sent_at", + "sent_by", + "updated_at", + "status", + "reference", + "template", + "service", + "job", + "api_key", + "body", + "content_char_count", + "subject" + ] + } +} diff --git a/tests/app/public_contracts/sms_notification.json b/tests/app/public_contracts/sms_notification.json new file mode 100644 index 000000000..816a2056a --- /dev/null +++ b/tests/app/public_contracts/sms_notification.json @@ -0,0 +1,106 @@ +{ + "sms_notification": { + "description": "Single sms notification schema - as returned by GET /notification and GET /notification/{}", + "type": "object", + "properties": { + "id": {"$ref": "definitions.json#/uuid"}, + "to": {"type": "string"}, + "job_row_number": {"oneOf":[ + {"type": "number"}, + {"type": "null"} + ]}, + "template_version": {"type": "number"}, + "billable_units": {"type": "number"}, + "notification_type": { + "type": "string", + "enum": ["sms"] + }, + "created_at": {"$ref": "definitions.json#/datetime"}, + "sent_at": {"oneOf":[ + {"$ref": "definitions.json#/datetime"}, + {"type": "null"} + ]}, + "sent_by": {"oneOf":[ + {"type": "string"}, + {"type": "null"} + ]}, + "updated_at": {"oneOf":[ + {"$ref": "definitions.json#/datetime"}, + {"type": "null"} + ]}, + "status": { + "type": "string", + "enum": [ + "created", + "sending", + "delivered", + "pending", + "failed", + "technical-failure", + "temporary-failure", + "permanent-failure" + ] + }, + "reference": {"oneOf":[ + {"type": "string"}, + {"type": "null"} + ]}, + "template": { + "type": "object", + "properties": { + "id": {"$ref": "definitions.json#/uuid"}, + "name": {"type": "string"}, + "template_type": { + "type": "string", + "enum": ["sms"] + }, + "version": {"type": "number"} + }, + "additionalProperties": false, + "required": ["id", "name", "template_type", "version"] + }, + "service": {"$ref": "definitions.json#/uuid"}, + "job": { + "oneOf": [ + { + "type": "object", + "properties": { + "id": {"$ref": "definitions.json#/uuid"}, + "original_file_name": {"type": "string"} + }, + "additionalProperties": false, + "required": ["id", "original_file_name"] + }, + {"type": "null"} + ] + }, + "api_key": {"oneOf":[ + {"$ref": "definitions.json#/uuid"}, + {"type": "null"} + ]}, + "body": {"type": "string"}, + "content_char_count": {"type": "null"} + }, + "additionalProperties": false, + "required": [ + "id", + "to", + "job_row_number", + "template_version", + "billable_units", + "notification_type", + "created_at", + "sent_at", + "sent_by", + "updated_at", + "status", + "reference", + "template", + "service", + "job", + "api_key", + "body", + "content_char_count" + ] + } +} diff --git a/tests/app/public_contracts/test_GET_notification.py b/tests/app/public_contracts/test_GET_notification.py index d048e34e2..a9cb0fce4 100644 --- a/tests/app/public_contracts/test_GET_notification.py +++ b/tests/app/public_contracts/test_GET_notification.py @@ -5,26 +5,25 @@ import jsonschema from tests import create_authorization_header +def validate(json_string, schema_filename): + resolver = jsonschema.RefResolver('file://' + os.path.dirname(__file__) + '/', None) + with open(os.path.join(os.path.dirname(__file__), schema_filename)) as schema: + jsonschema.validate( + json.loads(json_string), + json.load(schema), + format_checker=jsonschema.FormatChecker(), + resolver=resolver + ) def test_get_sms_contract(client, sample_notification): auth_header = create_authorization_header(service_id=sample_notification.service_id) response = client.get('/notifications/{}'.format(sample_notification.id), headers=[auth_header]) - with open(os.path.join(os.path.dirname(__file__), './GET_notification_return_sms.json')) as schema: - jsonschema.validate( - json.loads(response.get_data(as_text=True)), - json.load(schema), - format_checker=jsonschema.FormatChecker() - ) + validate(response.get_data(as_text=True), './GET_notification_return_sms.json') def test_get_email_contract(client, sample_email_notification): auth_header = create_authorization_header(service_id=sample_email_notification.service_id) response = client.get('/notifications/{}'.format(sample_email_notification.id), headers=[auth_header]) - with open(os.path.join(os.path.dirname(__file__), './GET_notification_return_email.json')) as schema: - jsonschema.validate( - json.loads(response.get_data(as_text=True)), - json.load(schema), - format_checker=jsonschema.FormatChecker() - ) + validate(response.get_data(as_text=True), './GET_notification_return_email.json') From cb0491cbff583e32c28780429a33d78adac349bf Mon Sep 17 00:00:00 2001 From: Leo Hemsted Date: Tue, 30 Aug 2016 19:07:46 +0100 Subject: [PATCH 6/9] add test for GET /notification simple schema with oneOf [email, sms]. also fixed error where ref'd schemas weren't being picked up --- .../GET_notification_return_email.json | 6 +- .../GET_notification_return_sms.json | 6 +- .../GET_notifications_return.json | 26 +++ tests/app/public_contracts/definitions.json | 2 +- .../public_contracts/email_notification.json | 208 +++++++++--------- .../public_contracts/sms_notification.json | 204 +++++++++-------- .../public_contracts/test_GET_notification.py | 7 + 7 files changed, 246 insertions(+), 213 deletions(-) create mode 100644 tests/app/public_contracts/GET_notifications_return.json diff --git a/tests/app/public_contracts/GET_notification_return_email.json b/tests/app/public_contracts/GET_notification_return_email.json index 949033e6b..e6fb6b19f 100644 --- a/tests/app/public_contracts/GET_notification_return_email.json +++ b/tests/app/public_contracts/GET_notification_return_email.json @@ -8,8 +8,10 @@ "properties": { "notification": {"$ref": "email_notification.json"} }, - "additionalProperties": false + "additionalProperties": false, + "required": ["notification"] } }, - "additionalProperties": false + "additionalProperties": false, + "required": ["data"] } diff --git a/tests/app/public_contracts/GET_notification_return_sms.json b/tests/app/public_contracts/GET_notification_return_sms.json index 356428fde..2127ffd46 100644 --- a/tests/app/public_contracts/GET_notification_return_sms.json +++ b/tests/app/public_contracts/GET_notification_return_sms.json @@ -8,8 +8,10 @@ "properties": { "notification": {"$ref": "sms_notification.json"} }, - "additionalProperties": false + "additionalProperties": false, + "required": ["notification"] } }, - "additionalProperties": false + "additionalProperties": false, + "required": ["data"] } diff --git a/tests/app/public_contracts/GET_notifications_return.json b/tests/app/public_contracts/GET_notifications_return.json new file mode 100644 index 000000000..7939dd8f1 --- /dev/null +++ b/tests/app/public_contracts/GET_notifications_return.json @@ -0,0 +1,26 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "GET notification return schema - for sms notifications", + "type" : "object", + "properties": { + "notifications": { + "type": "array", + "items": { + "oneOf": [ + {"$ref": "sms_notification.json"}, + {"$ref": "email_notification.json"} + ] + } + }, + "links": { + "type": "object", + "additionalProperties": false + }, + "page_size": {"type": "number"}, + "total": {"type": "number"} + }, + "additionalProperties": false, + "required": [ + "notifications", "links", "page_size", "total" + ] +} diff --git a/tests/app/public_contracts/definitions.json b/tests/app/public_contracts/definitions.json index d8a2ea3ef..5b12591dc 100644 --- a/tests/app/public_contracts/definitions.json +++ b/tests/app/public_contracts/definitions.json @@ -8,5 +8,5 @@ "datetime": { "type": "string", "format": "date-time" - }, + } } diff --git a/tests/app/public_contracts/email_notification.json b/tests/app/public_contracts/email_notification.json index 6de386eea..013fb49ff 100644 --- a/tests/app/public_contracts/email_notification.json +++ b/tests/app/public_contracts/email_notification.json @@ -1,108 +1,106 @@ { - "email_notification": { - "description": "Single email notification schema - as returned by GET /notification and GET /notification/{}", - "type": "object", - "properties": { - "id": {"$ref": "definitions.json#/uuid"}, - "to": {"type": "string", "format": "email"}, - "job_row_number": {"oneOf":[ - {"type": "number"}, - {"type": "null"} - ]}, - "template_version": {"type": "number"}, - "billable_units": {"type": "number"}, - "notification_type": { - "type": "string", - "enum": ["email"] - }, - "created_at": {"$ref": "definitions.json#/datetime"}, - "sent_at": {"oneOf":[ - {"$ref": "definitions.json#/datetime"}, - {"type": "null"} - ]}, - "sent_by": {"oneOf":[ - {"type": "string"}, - {"type": "null"} - ]}, - "updated_at": {"oneOf":[ - {"$ref": "definitions.json#/datetime"}, - {"type": "null"} - ]}, - "status": { - "type": "string", - "enum": [ - "created", - "sending", - "delivered", - "pending", - "failed", - "technical-failure", - "temporary-failure", - "permanent-failure" - ] - }, - "reference": {"oneOf":[ - {"type": "string"}, - {"type": "null"} - ]}, - "template": { - "type": "object", - "properties": { - "id": {"$ref": "definitions.json#/uuid"}, - "name": {"type": "string"}, - "template_type": { - "type": "string", - "enum": ["email"] - }, - "version": {"type": "number"} - }, - "additionalProperties": false, - "required": ["id", "name", "template_type", "version"] - }, - "service": {"$ref": "definitions.json#/uuid"}, - "job": { - "oneOf": [ - { - "type": "object", - "properties": { - "id": {"$ref": "definitions.json#/uuid"}, - "original_file_name": {"type": "string"} - }, - "additionalProperties": false, - "required": ["id", "original_file_name"] - }, - {"type": "null"} - ] - }, - "api_key": {"oneOf":[ - {"$ref": "definitions.json#/uuid"}, - {"type": "null"} - ]}, - "body": {"type": "string"}, - "content_char_count": {"type": "null"}, - "subject": {"type": "string"} + "description": "Single email notification schema - as returned by GET /notification and GET /notification/{}", + "type": "object", + "properties": { + "id": {"$ref": "definitions.json#/uuid"}, + "to": {"type": "string", "format": "email"}, + "job_row_number": {"oneOf":[ + {"type": "number"}, + {"type": "null"} + ]}, + "template_version": {"type": "number"}, + "billable_units": {"type": "number"}, + "notification_type": { + "type": "string", + "enum": ["email"] }, - "additionalProperties": false, - "required": [ - "id", - "to", - "job_row_number", - "template_version", - "billable_units", - "notification_type", - "created_at", - "sent_at", - "sent_by", - "updated_at", - "status", - "reference", - "template", - "service", - "job", - "api_key", - "body", - "content_char_count", - "subject" - ] - } + "created_at": {"$ref": "definitions.json#/datetime"}, + "sent_at": {"oneOf":[ + {"$ref": "definitions.json#/datetime"}, + {"type": "null"} + ]}, + "sent_by": {"oneOf":[ + {"type": "string"}, + {"type": "null"} + ]}, + "updated_at": {"oneOf":[ + {"$ref": "definitions.json#/datetime"}, + {"type": "null"} + ]}, + "status": { + "type": "string", + "enum": [ + "created", + "sending", + "delivered", + "pending", + "failed", + "technical-failure", + "temporary-failure", + "permanent-failure" + ] + }, + "reference": {"oneOf":[ + {"type": "string"}, + {"type": "null"} + ]}, + "template": { + "type": "object", + "properties": { + "id": {"$ref": "definitions.json#/uuid"}, + "name": {"type": "string"}, + "template_type": { + "type": "string", + "enum": ["email"] + }, + "version": {"type": "number"} + }, + "additionalProperties": false, + "required": ["id", "name", "template_type", "version"] + }, + "service": {"$ref": "definitions.json#/uuid"}, + "job": { + "oneOf": [ + { + "type": "object", + "properties": { + "id": {"$ref": "definitions.json#/uuid"}, + "original_file_name": {"type": "string"} + }, + "additionalProperties": false, + "required": ["id", "original_file_name"] + }, + {"type": "null"} + ] + }, + "api_key": {"oneOf":[ + {"$ref": "definitions.json#/uuid"}, + {"type": "null"} + ]}, + "body": {"type": "string"}, + "content_char_count": {"type": "null"}, + "subject": {"type": "string"} + }, + "additionalProperties": false, + "required": [ + "id", + "to", + "job_row_number", + "template_version", + "billable_units", + "notification_type", + "created_at", + "sent_at", + "sent_by", + "updated_at", + "status", + "reference", + "template", + "service", + "job", + "api_key", + "body", + "content_char_count", + "subject" + ] } diff --git a/tests/app/public_contracts/sms_notification.json b/tests/app/public_contracts/sms_notification.json index 816a2056a..d81def6ea 100644 --- a/tests/app/public_contracts/sms_notification.json +++ b/tests/app/public_contracts/sms_notification.json @@ -1,106 +1,104 @@ { - "sms_notification": { - "description": "Single sms notification schema - as returned by GET /notification and GET /notification/{}", - "type": "object", - "properties": { - "id": {"$ref": "definitions.json#/uuid"}, - "to": {"type": "string"}, - "job_row_number": {"oneOf":[ - {"type": "number"}, - {"type": "null"} - ]}, - "template_version": {"type": "number"}, - "billable_units": {"type": "number"}, - "notification_type": { - "type": "string", - "enum": ["sms"] - }, - "created_at": {"$ref": "definitions.json#/datetime"}, - "sent_at": {"oneOf":[ - {"$ref": "definitions.json#/datetime"}, - {"type": "null"} - ]}, - "sent_by": {"oneOf":[ - {"type": "string"}, - {"type": "null"} - ]}, - "updated_at": {"oneOf":[ - {"$ref": "definitions.json#/datetime"}, - {"type": "null"} - ]}, - "status": { - "type": "string", - "enum": [ - "created", - "sending", - "delivered", - "pending", - "failed", - "technical-failure", - "temporary-failure", - "permanent-failure" - ] - }, - "reference": {"oneOf":[ - {"type": "string"}, - {"type": "null"} - ]}, - "template": { - "type": "object", - "properties": { - "id": {"$ref": "definitions.json#/uuid"}, - "name": {"type": "string"}, - "template_type": { - "type": "string", - "enum": ["sms"] - }, - "version": {"type": "number"} - }, - "additionalProperties": false, - "required": ["id", "name", "template_type", "version"] - }, - "service": {"$ref": "definitions.json#/uuid"}, - "job": { - "oneOf": [ - { - "type": "object", - "properties": { - "id": {"$ref": "definitions.json#/uuid"}, - "original_file_name": {"type": "string"} - }, - "additionalProperties": false, - "required": ["id", "original_file_name"] - }, - {"type": "null"} - ] - }, - "api_key": {"oneOf":[ - {"$ref": "definitions.json#/uuid"}, - {"type": "null"} - ]}, - "body": {"type": "string"}, - "content_char_count": {"type": "null"} + "description": "Single sms notification schema - as returned by GET /notification and GET /notification/{}", + "type": "object", + "properties": { + "id": {"$ref": "definitions.json#/uuid"}, + "to": {"type": "string"}, + "job_row_number": {"oneOf":[ + {"type": "number"}, + {"type": "null"} + ]}, + "template_version": {"type": "number"}, + "billable_units": {"type": "number"}, + "notification_type": { + "type": "string", + "enum": ["sms"] }, - "additionalProperties": false, - "required": [ - "id", - "to", - "job_row_number", - "template_version", - "billable_units", - "notification_type", - "created_at", - "sent_at", - "sent_by", - "updated_at", - "status", - "reference", - "template", - "service", - "job", - "api_key", - "body", - "content_char_count" - ] - } + "created_at": {"$ref": "definitions.json#/datetime"}, + "sent_at": {"oneOf":[ + {"$ref": "definitions.json#/datetime"}, + {"type": "null"} + ]}, + "sent_by": {"oneOf":[ + {"type": "string"}, + {"type": "null"} + ]}, + "updated_at": {"oneOf":[ + {"$ref": "definitions.json#/datetime"}, + {"type": "null"} + ]}, + "status": { + "type": "string", + "enum": [ + "created", + "sending", + "delivered", + "pending", + "failed", + "technical-failure", + "temporary-failure", + "permanent-failure" + ] + }, + "reference": {"oneOf":[ + {"type": "string"}, + {"type": "null"} + ]}, + "template": { + "type": "object", + "properties": { + "id": {"$ref": "definitions.json#/uuid"}, + "name": {"type": "string"}, + "template_type": { + "type": "string", + "enum": ["sms"] + }, + "version": {"type": "number"} + }, + "additionalProperties": false, + "required": ["id", "name", "template_type", "version"] + }, + "service": {"$ref": "definitions.json#/uuid"}, + "job": { + "oneOf": [ + { + "type": "object", + "properties": { + "id": {"$ref": "definitions.json#/uuid"}, + "original_file_name": {"type": "string"} + }, + "additionalProperties": false, + "required": ["id", "original_file_name"] + }, + {"type": "null"} + ] + }, + "api_key": {"oneOf":[ + {"$ref": "definitions.json#/uuid"}, + {"type": "null"} + ]}, + "body": {"type": "string"}, + "content_char_count": {"type": "number"} + }, + "additionalProperties": false, + "required": [ + "id", + "to", + "job_row_number", + "template_version", + "billable_units", + "notification_type", + "created_at", + "sent_at", + "sent_by", + "updated_at", + "status", + "reference", + "template", + "service", + "job", + "api_key", + "body", + "content_char_count" + ] } diff --git a/tests/app/public_contracts/test_GET_notification.py b/tests/app/public_contracts/test_GET_notification.py index a9cb0fce4..d7a03b77a 100644 --- a/tests/app/public_contracts/test_GET_notification.py +++ b/tests/app/public_contracts/test_GET_notification.py @@ -27,3 +27,10 @@ def test_get_email_contract(client, sample_email_notification): response = client.get('/notifications/{}'.format(sample_email_notification.id), headers=[auth_header]) validate(response.get_data(as_text=True), './GET_notification_return_email.json') + + +def test_get_notifications_contract(client, sample_notification, sample_email_notification): + auth_header = create_authorization_header(service_id=sample_notification.service_id) + response = client.get('/notifications', headers=[auth_header]) + + validate(response.get_data(as_text=True), './GET_notifications_return.json') From fabbb8b01b01a87c93e9a9a458d483cdc561d35d Mon Sep 17 00:00:00 2001 From: Leo Hemsted Date: Wed, 31 Aug 2016 11:53:54 +0100 Subject: [PATCH 7/9] separate tests for api and job notifications --- tests/app/public_contracts/__init__.py | 14 +++++ .../public_contracts/test_GET_notification.py | 55 +++++++++++++------ 2 files changed, 53 insertions(+), 16 deletions(-) diff --git a/tests/app/public_contracts/__init__.py b/tests/app/public_contracts/__init__.py index e69de29bb..cf57c3295 100644 --- a/tests/app/public_contracts/__init__.py +++ b/tests/app/public_contracts/__init__.py @@ -0,0 +1,14 @@ +import os + +from flask import json +import jsonschema + +def validate(json_string, schema_filename): + resolver = jsonschema.RefResolver('file://' + os.path.dirname(__file__) + '/', None) + with open(os.path.join(os.path.dirname(__file__), schema_filename)) as schema: + jsonschema.validate( + json.loads(json_string), + json.load(schema), + format_checker=jsonschema.FormatChecker(), + resolver=resolver + ) diff --git a/tests/app/public_contracts/test_GET_notification.py b/tests/app/public_contracts/test_GET_notification.py index d7a03b77a..e9a3c44d5 100644 --- a/tests/app/public_contracts/test_GET_notification.py +++ b/tests/app/public_contracts/test_GET_notification.py @@ -1,28 +1,51 @@ -import os - -from flask import json -import jsonschema - +from . import validate +from app.models import ApiKey, KEY_TYPE_NORMAL +from app.dao.notifications_dao import dao_update_notification +from app.dao.api_key_dao import save_model_api_key from tests import create_authorization_header -def validate(json_string, schema_filename): - resolver = jsonschema.RefResolver('file://' + os.path.dirname(__file__) + '/', None) - with open(os.path.join(os.path.dirname(__file__), schema_filename)) as schema: - jsonschema.validate( - json.loads(json_string), - json.load(schema), - format_checker=jsonschema.FormatChecker(), - resolver=resolver - ) -def test_get_sms_contract(client, sample_notification): +def test_get_api_sms_contract(client, sample_notification): + api_key = ApiKey(service=sample_notification.service, + name='api_key', + created_by=sample_notification.service.created_by, + key_type=KEY_TYPE_NORMAL) + save_model_api_key(api_key) + sample_notification.job = None + sample_notification.api_key = api_key + sample_notification.key_type = KEY_TYPE_NORMAL + dao_update_notification(sample_notification) auth_header = create_authorization_header(service_id=sample_notification.service_id) response = client.get('/notifications/{}'.format(sample_notification.id), headers=[auth_header]) validate(response.get_data(as_text=True), './GET_notification_return_sms.json') -def test_get_email_contract(client, sample_email_notification): +def test_get_api_email_contract(client, sample_email_notification): + api_key = ApiKey(service=sample_email_notification.service, + name='api_key', + created_by=sample_email_notification.service.created_by, + key_type=KEY_TYPE_NORMAL) + save_model_api_key(api_key) + sample_email_notification.job = None + sample_email_notification.api_key = api_key + sample_email_notification.key_type = KEY_TYPE_NORMAL + dao_update_notification(sample_email_notification) + + auth_header = create_authorization_header(service_id=sample_email_notification.service_id) + response = client.get('/notifications/{}'.format(sample_email_notification.id), headers=[auth_header]) + + validate(response.get_data(as_text=True), './GET_notification_return_email.json') + + +def test_get_job_sms_contract(client, sample_notification): + auth_header = create_authorization_header(service_id=sample_notification.service_id) + response = client.get('/notifications/{}'.format(sample_notification.id), headers=[auth_header]) + + validate(response.get_data(as_text=True), './GET_notification_return_sms.json') + + +def test_get_job_email_contract(client, sample_email_notification): auth_header = create_authorization_header(service_id=sample_email_notification.service_id) response = client.get('/notifications/{}'.format(sample_email_notification.id), headers=[auth_header]) From c91358673fa410f2000eff20327044a239ffefc4 Mon Sep 17 00:00:00 2001 From: Leo Hemsted Date: Wed, 31 Aug 2016 12:22:05 +0100 Subject: [PATCH 8/9] add POST response tests assert that the response for emails and sms is formatted as expected also moved schemas into subdirectory to make folder more legible --- tests/app/public_contracts/__init__.py | 5 ++- .../GET_notification_return_email.json | 0 .../GET_notification_return_sms.json | 0 .../GET_notifications_return.json | 0 .../POST_notification_return_email.json | 27 ++++++++++++ .../schemas/POST_notification_return_sms.json | 26 +++++++++++ .../{ => schemas}/definitions.json | 0 .../{ => schemas}/email_notification.json | 0 .../{ => schemas}/sms_notification.json | 0 .../public_contracts/test_GET_notification.py | 10 ++--- .../test_POST_notification.py | 44 +++++++++++++++++++ 11 files changed, 105 insertions(+), 7 deletions(-) rename tests/app/public_contracts/{ => schemas}/GET_notification_return_email.json (100%) rename tests/app/public_contracts/{ => schemas}/GET_notification_return_sms.json (100%) rename tests/app/public_contracts/{ => schemas}/GET_notifications_return.json (100%) create mode 100644 tests/app/public_contracts/schemas/POST_notification_return_email.json create mode 100644 tests/app/public_contracts/schemas/POST_notification_return_sms.json rename tests/app/public_contracts/{ => schemas}/definitions.json (100%) rename tests/app/public_contracts/{ => schemas}/email_notification.json (100%) rename tests/app/public_contracts/{ => schemas}/sms_notification.json (100%) create mode 100644 tests/app/public_contracts/test_POST_notification.py diff --git a/tests/app/public_contracts/__init__.py b/tests/app/public_contracts/__init__.py index cf57c3295..c6f7eee80 100644 --- a/tests/app/public_contracts/__init__.py +++ b/tests/app/public_contracts/__init__.py @@ -4,8 +4,9 @@ from flask import json import jsonschema def validate(json_string, schema_filename): - resolver = jsonschema.RefResolver('file://' + os.path.dirname(__file__) + '/', None) - with open(os.path.join(os.path.dirname(__file__), schema_filename)) as schema: + schema_dir = os.path.join(os.path.dirname(__file__), 'schemas') + resolver = jsonschema.RefResolver('file://' + schema_dir + '/', None) + with open(os.path.join(schema_dir, schema_filename)) as schema: jsonschema.validate( json.loads(json_string), json.load(schema), diff --git a/tests/app/public_contracts/GET_notification_return_email.json b/tests/app/public_contracts/schemas/GET_notification_return_email.json similarity index 100% rename from tests/app/public_contracts/GET_notification_return_email.json rename to tests/app/public_contracts/schemas/GET_notification_return_email.json diff --git a/tests/app/public_contracts/GET_notification_return_sms.json b/tests/app/public_contracts/schemas/GET_notification_return_sms.json similarity index 100% rename from tests/app/public_contracts/GET_notification_return_sms.json rename to tests/app/public_contracts/schemas/GET_notification_return_sms.json diff --git a/tests/app/public_contracts/GET_notifications_return.json b/tests/app/public_contracts/schemas/GET_notifications_return.json similarity index 100% rename from tests/app/public_contracts/GET_notifications_return.json rename to tests/app/public_contracts/schemas/GET_notifications_return.json diff --git a/tests/app/public_contracts/schemas/POST_notification_return_email.json b/tests/app/public_contracts/schemas/POST_notification_return_email.json new file mode 100644 index 000000000..bd84f798a --- /dev/null +++ b/tests/app/public_contracts/schemas/POST_notification_return_email.json @@ -0,0 +1,27 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "POST notification return schema - for email notifications", + "type" : "object", + "properties": { + "data": { + "type": "object", + "properties": { + "notification": { + "type": "object", + "properties": { + "id": {"$ref": "definitions.json#/uuid"} + }, + "additionalProperties": false, + "required": ["id"] + }, + "body": {"type": "string"}, + "template_version": {"type": "number"}, + "subject": {"type": "string"} + }, + "additionalProperties": false, + "required": ["notification", "body", "template_version", "subject"] + } + }, + "additionalProperties": false, + "required": ["data"] +} diff --git a/tests/app/public_contracts/schemas/POST_notification_return_sms.json b/tests/app/public_contracts/schemas/POST_notification_return_sms.json new file mode 100644 index 000000000..3119c6d73 --- /dev/null +++ b/tests/app/public_contracts/schemas/POST_notification_return_sms.json @@ -0,0 +1,26 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "POST notification return schema - for sms notifications", + "type" : "object", + "properties": { + "data": { + "type": "object", + "properties": { + "notification": { + "type": "object", + "properties": { + "id": {"$ref": "definitions.json#/uuid"} + }, + "additionalProperties": false, + "required": ["id"] + }, + "body": {"type": "string"}, + "template_version": {"type": "number"} + }, + "additionalProperties": false, + "required": ["notification", "body", "template_version"] + } + }, + "additionalProperties": false, + "required": ["data"] +} diff --git a/tests/app/public_contracts/definitions.json b/tests/app/public_contracts/schemas/definitions.json similarity index 100% rename from tests/app/public_contracts/definitions.json rename to tests/app/public_contracts/schemas/definitions.json diff --git a/tests/app/public_contracts/email_notification.json b/tests/app/public_contracts/schemas/email_notification.json similarity index 100% rename from tests/app/public_contracts/email_notification.json rename to tests/app/public_contracts/schemas/email_notification.json diff --git a/tests/app/public_contracts/sms_notification.json b/tests/app/public_contracts/schemas/sms_notification.json similarity index 100% rename from tests/app/public_contracts/sms_notification.json rename to tests/app/public_contracts/schemas/sms_notification.json diff --git a/tests/app/public_contracts/test_GET_notification.py b/tests/app/public_contracts/test_GET_notification.py index e9a3c44d5..fdc13e078 100644 --- a/tests/app/public_contracts/test_GET_notification.py +++ b/tests/app/public_contracts/test_GET_notification.py @@ -18,7 +18,7 @@ def test_get_api_sms_contract(client, sample_notification): auth_header = create_authorization_header(service_id=sample_notification.service_id) response = client.get('/notifications/{}'.format(sample_notification.id), headers=[auth_header]) - validate(response.get_data(as_text=True), './GET_notification_return_sms.json') + validate(response.get_data(as_text=True), 'GET_notification_return_sms.json') def test_get_api_email_contract(client, sample_email_notification): @@ -35,25 +35,25 @@ def test_get_api_email_contract(client, sample_email_notification): auth_header = create_authorization_header(service_id=sample_email_notification.service_id) response = client.get('/notifications/{}'.format(sample_email_notification.id), headers=[auth_header]) - validate(response.get_data(as_text=True), './GET_notification_return_email.json') + validate(response.get_data(as_text=True), 'GET_notification_return_email.json') def test_get_job_sms_contract(client, sample_notification): auth_header = create_authorization_header(service_id=sample_notification.service_id) response = client.get('/notifications/{}'.format(sample_notification.id), headers=[auth_header]) - validate(response.get_data(as_text=True), './GET_notification_return_sms.json') + validate(response.get_data(as_text=True), 'GET_notification_return_sms.json') def test_get_job_email_contract(client, sample_email_notification): auth_header = create_authorization_header(service_id=sample_email_notification.service_id) response = client.get('/notifications/{}'.format(sample_email_notification.id), headers=[auth_header]) - validate(response.get_data(as_text=True), './GET_notification_return_email.json') + validate(response.get_data(as_text=True), 'GET_notification_return_email.json') def test_get_notifications_contract(client, sample_notification, sample_email_notification): auth_header = create_authorization_header(service_id=sample_notification.service_id) response = client.get('/notifications', headers=[auth_header]) - validate(response.get_data(as_text=True), './GET_notifications_return.json') + validate(response.get_data(as_text=True), 'GET_notifications_return.json') diff --git a/tests/app/public_contracts/test_POST_notification.py b/tests/app/public_contracts/test_POST_notification.py new file mode 100644 index 000000000..ffb91210c --- /dev/null +++ b/tests/app/public_contracts/test_POST_notification.py @@ -0,0 +1,44 @@ +from flask import json + +from . import validate +from tests import create_authorization_header + + +def test_post_sms_contract(client, mocker, sample_template): + mocker.patch('app.celery.tasks.send_sms.apply_async') + mocker.patch('app.encryption.encrypt', return_value="something_encrypted") + + data = { + 'to': '07700 900 855', + 'template': str(sample_template.id) + } + + auth_header = create_authorization_header(service_id=sample_template.service_id) + + response = client.post( + path='/notifications/sms', + data=json.dumps(data), + headers=[('Content-Type', 'application/json'), auth_header] + ) + + validate(response.get_data(as_text=True), 'POST_notification_return_sms.json') + + +def test_post_email_contract(client, mocker, sample_email_template): + mocker.patch('app.celery.tasks.send_sms.apply_async') + mocker.patch('app.encryption.encrypt', return_value="something_encrypted") + + data = { + 'to': 'foo@bar.com', + 'template': str(sample_email_template.id) + } + + auth_header = create_authorization_header(service_id=sample_email_template.service_id) + + response = client.post( + path='/notifications/email', + data=json.dumps(data), + headers=[('Content-Type', 'application/json'), auth_header] + ) + + validate(response.get_data(as_text=True), 'POST_notification_return_email.json') From 7240df06412d86ded1a7daa903a26feee528d717 Mon Sep 17 00:00:00 2001 From: Leo Hemsted Date: Wed, 31 Aug 2016 12:39:11 +0100 Subject: [PATCH 9/9] replace mock with unittest.mock --- tests/app/celery/test_tasks.py | 2 +- tests/app/public_contracts/__init__.py | 1 + tests/app/test_statsd_decorators.py | 2 +- tests/conftest.py | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/app/celery/test_tasks.py b/tests/app/celery/test_tasks.py index 547ee769e..d8f90dcd3 100644 --- a/tests/app/celery/test_tasks.py +++ b/tests/app/celery/test_tasks.py @@ -3,7 +3,7 @@ from datetime import datetime import pytest from freezegun import freeze_time -from mock import ANY +from unittest.mock import ANY from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.orm.exc import NoResultFound diff --git a/tests/app/public_contracts/__init__.py b/tests/app/public_contracts/__init__.py index c6f7eee80..c3276dd83 100644 --- a/tests/app/public_contracts/__init__.py +++ b/tests/app/public_contracts/__init__.py @@ -3,6 +3,7 @@ import os from flask import json import jsonschema + def validate(json_string, schema_filename): schema_dir = os.path.join(os.path.dirname(__file__), 'schemas') resolver = jsonschema.RefResolver('file://' + schema_dir + '/', None) diff --git a/tests/app/test_statsd_decorators.py b/tests/app/test_statsd_decorators.py index 3470f9038..dc904f2e1 100644 --- a/tests/app/test_statsd_decorators.py +++ b/tests/app/test_statsd_decorators.py @@ -1,4 +1,4 @@ -from mock import ANY +from unittest.mock import ANY from app.statsd_decorators import statsd import app diff --git a/tests/conftest.py b/tests/conftest.py index c5c57ae7e..abde85bf9 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,7 +1,7 @@ import os import boto3 -import mock +from unittest import mock import pytest from alembic.command import upgrade from alembic.config import Config