Skip to content

Commit aebaea1

Browse files
author
Leo Hemsted
committed
add public contract tests
use jsonschema to test the GET /notification/{} endpoint to highlight any key name/format/type changes
1 parent b21c8de commit aebaea1

File tree

6 files changed

+287
-38
lines changed

6 files changed

+287
-38
lines changed

requirements_for_test.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,5 @@ moto==0.4.25
88
flex==5.8.0
99
freezegun==0.3.7
1010
requests-mock==1.0.0
11+
jsonschema==2.5.1
12+
strict-rfc3339==0.7

tests/app/notifications/test_rest.py

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -625,44 +625,6 @@ def test_get_notifications_for_service_returns_merged_template_content(notify_ap
625625
}
626626

627627

628-
def test_get_notification_public_api_format_is_not_changed(notify_api, sample_notification):
629-
with notify_api.test_request_context(), notify_api.test_client() as client:
630-
auth_header = create_authorization_header(service_id=sample_notification.service_id)
631-
632-
response = client.get(
633-
'/notifications/{}'.format(sample_notification.id),
634-
headers=[auth_header])
635-
636-
assert response.status_code == 200
637-
notification = json.loads(response.get_data(as_text=True))['data']['notification']
638-
# you should never remove things from this list!
639-
assert set(notification.keys()) == {
640-
# straight from db
641-
'id',
642-
'to',
643-
'job_row_number',
644-
'template_version',
645-
'billable_units',
646-
'notification_type',
647-
'created_at',
648-
'sent_at',
649-
'sent_by',
650-
'updated_at',
651-
'status',
652-
'reference',
653-
654-
# relationships
655-
'template',
656-
'service',
657-
'job',
658-
'api_key',
659-
660-
# other
661-
'body',
662-
'content_char_count'
663-
}
664-
665-
666628
def test_get_notification_selects_correct_template_for_personalisation(notify_api,
667629
notify_db,
668630
notify_db_session,
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-04/schema#",
3+
"description": "GET notification return schema - for SMS notifications",
4+
"type" : "object",
5+
"properties": {
6+
"data": {
7+
"type": "object",
8+
"properties": {
9+
"notification": {
10+
"type": "object",
11+
"properties": {
12+
"id": {"$ref": "#/definitions/uuid"},
13+
"to": {"type": "string", "format": "email"},
14+
"job_row_number": {"oneOf":[
15+
{"type": "number"},
16+
{"type": "null"}
17+
]},
18+
"template_version": {"type": "number"},
19+
"billable_units": {"type": "number"},
20+
"notification_type": {
21+
"type": "string",
22+
"enum": ["email"]
23+
},
24+
"created_at": {"$ref": "#/definitions/datetime"},
25+
"sent_at": {"oneOf":[
26+
{"$ref": "#/definitions/datetime"},
27+
{"type": "null"}
28+
]},
29+
"sent_by": {"oneOf":[
30+
{"type": "string"},
31+
{"type": "null"}
32+
]},
33+
"updated_at": {"oneOf":[
34+
{"$ref": "#/definitions/datetime"},
35+
{"type": "null"}
36+
]},
37+
"status": {
38+
"type": "string",
39+
"enum": [
40+
"created",
41+
"sending",
42+
"delivered",
43+
"pending",
44+
"failed",
45+
"technical-failure",
46+
"temporary-failure",
47+
"permanent-failure"
48+
]
49+
},
50+
"reference": {"oneOf":[
51+
{"type": "string"},
52+
{"type": "null"}
53+
]},
54+
"template": {
55+
"type": "object",
56+
"properties": {
57+
"id": {"$ref": "#/definitions/uuid"},
58+
"name": {"type": "string"},
59+
"template_type": {
60+
"type": "string",
61+
"enum": ["email"]
62+
},
63+
"version": {"type": "number"}
64+
},
65+
"additionalProperties": false,
66+
"required": ["id", "name", "template_type", "version"]
67+
},
68+
"service": {"$ref": "#/definitions/uuid"},
69+
"job": {
70+
"oneOf": [
71+
{
72+
"type": "object",
73+
"properties": {
74+
"id": {"$ref": "#/definitions/uuid"},
75+
"original_file_name": {"type": "string"}
76+
},
77+
"additionalProperties": false,
78+
"required": ["id", "original_file_name"]
79+
},
80+
{"type": "null"}
81+
]
82+
},
83+
"api_key": {"oneOf":[
84+
{"$ref": "#/definitions/uuid"},
85+
{"type": "null"}
86+
]},
87+
"body": {"type": "string"},
88+
"content_char_count": {"type": "null"},
89+
"subject": {"type": "string"}
90+
},
91+
"additionalProperties": false,
92+
"required": [
93+
"id",
94+
"to",
95+
"job_row_number",
96+
"template_version",
97+
"billable_units",
98+
"notification_type",
99+
"created_at",
100+
"sent_at",
101+
"sent_by",
102+
"updated_at",
103+
"status",
104+
"reference",
105+
"template",
106+
"service",
107+
"job",
108+
"api_key",
109+
"body",
110+
"content_char_count"
111+
]
112+
}
113+
},
114+
"additionalProperties": false
115+
}
116+
},
117+
"additionalProperties": false,
118+
"definitions": {
119+
"uuid": {
120+
"type": "string",
121+
"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}$"
122+
},
123+
"datetime": {
124+
"type": "string",
125+
"format": "date-time"
126+
}
127+
}
128+
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-04/schema#",
3+
"description": "GET notification return schema - for SMS notifications",
4+
"type" : "object",
5+
"properties": {
6+
"data": {
7+
"type": "object",
8+
"properties": {
9+
"notification": {
10+
"type": "object",
11+
"properties": {
12+
"id": {"$ref": "#/definitions/uuid"},
13+
"to": {"type": "string"},
14+
"job_row_number": {"oneOf":[
15+
{"type": "number"},
16+
{"type": "null"}
17+
]},
18+
"template_version": {"type": "number"},
19+
"billable_units": {"type": "number"},
20+
"notification_type": {
21+
"type": "string",
22+
"enum": ["sms"]
23+
},
24+
"created_at": {"$ref": "#/definitions/datetime"},
25+
"sent_at": {"oneOf":[
26+
{"$ref": "#/definitions/datetime"},
27+
{"type": "null"}
28+
]},
29+
"sent_by": {"oneOf":[
30+
{"type": "string"},
31+
{"type": "null"}
32+
]},
33+
"updated_at": {"oneOf":[
34+
{"$ref": "#/definitions/datetime"},
35+
{"type": "null"}
36+
]},
37+
"status": {
38+
"type": "string",
39+
"enum": [
40+
"created",
41+
"sending",
42+
"delivered",
43+
"pending",
44+
"failed",
45+
"technical-failure",
46+
"temporary-failure",
47+
"permanent-failure"
48+
]
49+
},
50+
"reference": {"oneOf":[
51+
{"type": "string"},
52+
{"type": "null"}
53+
]},
54+
"template": {
55+
"type": "object",
56+
"properties": {
57+
"id": {"$ref": "#/definitions/uuid"},
58+
"name": {"type": "string"},
59+
"template_type": {
60+
"type": "string",
61+
"enum": ["sms"]
62+
},
63+
"version": {"type": "number"}
64+
},
65+
"additionalProperties": false,
66+
"required": ["id", "name", "template_type", "version"]
67+
},
68+
"service": {"$ref": "#/definitions/uuid"},
69+
"job": {
70+
"oneOf": [
71+
{
72+
"type": "object",
73+
"properties": {
74+
"id": {"$ref": "#/definitions/uuid"},
75+
"original_file_name": {"type": "string"}
76+
},
77+
"additionalProperties": false,
78+
"required": ["id", "original_file_name"]
79+
},
80+
{"type": "null"}
81+
]
82+
},
83+
"api_key": {"oneOf":[
84+
{"$ref": "#/definitions/uuid"},
85+
{"type": "null"}
86+
]},
87+
"body": {"type": "string"},
88+
"content_char_count": {"type": "number"}
89+
},
90+
"additionalProperties": false,
91+
"required": [
92+
"id",
93+
"to",
94+
"job_row_number",
95+
"template_version",
96+
"billable_units",
97+
"notification_type",
98+
"created_at",
99+
"sent_at",
100+
"sent_by",
101+
"updated_at",
102+
"status",
103+
"reference",
104+
"template",
105+
"service",
106+
"job",
107+
"api_key",
108+
"body",
109+
"content_char_count"
110+
]
111+
}
112+
},
113+
"additionalProperties": false
114+
}
115+
},
116+
"additionalProperties": false,
117+
"definitions": {
118+
"uuid": {
119+
"type": "string",
120+
"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}$"
121+
},
122+
"datetime": {
123+
"type": "string",
124+
"format": "date-time"
125+
}
126+
}
127+
}

tests/app/public_contracts/__init__.py

Whitespace-only changes.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import os
2+
3+
from flask import json
4+
import jsonschema
5+
6+
from tests import create_authorization_header
7+
8+
9+
def test_get_sms_contract(client, sample_notification):
10+
auth_header = create_authorization_header(service_id=sample_notification.service_id)
11+
response = client.get('/notifications/{}'.format(sample_notification.id), headers=[auth_header])
12+
13+
with open(os.path.join(os.path.dirname(__file__), './GET_notification_return_sms.json')) as schema:
14+
jsonschema.validate(
15+
json.loads(response.get_data(as_text=True)),
16+
json.load(schema),
17+
format_checker=jsonschema.FormatChecker()
18+
)
19+
20+
21+
def test_get_email_contract(client, sample_email_notification):
22+
auth_header = create_authorization_header(service_id=sample_email_notification.service_id)
23+
response = client.get('/notifications/{}'.format(sample_email_notification.id), headers=[auth_header])
24+
25+
with open(os.path.join(os.path.dirname(__file__), './GET_notification_return_email.json')) as schema:
26+
jsonschema.validate(
27+
json.loads(response.get_data(as_text=True)),
28+
json.load(schema),
29+
format_checker=jsonschema.FormatChecker()
30+
)

0 commit comments

Comments
 (0)