-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Replace mocks with VCR casettes for client testing
- Loading branch information
Showing
8 changed files
with
905 additions
and
95 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
interactions: | ||
- request: | ||
body: null | ||
headers: | ||
Accept: | ||
- '*/*' | ||
Accept-Encoding: | ||
- gzip, deflate | ||
Connection: | ||
- keep-alive | ||
User-Agent: | ||
- python-requests/2.32.3 | ||
method: GET | ||
uri: https://open-forms.test.maykin.opengem.nl/api/v2/public/forms | ||
response: | ||
body: | ||
string: '{"type":"https://open-forms.test.maykin.opengem.nl/fouten/AuthenticationFailed/","code":"authentication_failed","title":"Ongeldige | ||
authenticatiegegevens.","status":401,"detail":"Ongeldige token.","instance":"urn:uuid:b3f40157-9442-486c-aaba-037f9342c703"}' | ||
headers: | ||
Allow: | ||
- GET, HEAD, OPTIONS | ||
Cache-Control: | ||
- max-age=0, no-cache, no-store, must-revalidate, private | ||
Connection: | ||
- keep-alive | ||
Content-Language: | ||
- nl | ||
Content-Length: | ||
- '255' | ||
Content-Type: | ||
- application/json | ||
Cross-Origin-Opener-Policy: | ||
- same-origin | ||
Date: | ||
- Wed, 31 Jul 2024 08:05:44 GMT | ||
Expires: | ||
- Wed, 31 Jul 2024 08:05:44 GMT | ||
Pragma: | ||
- no-cache | ||
Referrer-Policy: | ||
- same-origin | ||
Set-Cookie: | ||
- csrftoken=rDnuLzLrAUGpIgp2gYxelwj7UGZEqCV6; expires=Wed, 30 Jul 2025 08:05:44 | ||
GMT; Max-Age=31449600; Path=/; SameSite=None; Secure | ||
- openforms_sessionid=8ev8ldwpo3vi2qsnw0l176htbcrcbg54; expires=Wed, 31 Jul | ||
2024 08:10:44 GMT; HttpOnly; Max-Age=300; Path=/; SameSite=None; Secure | ||
Strict-Transport-Security: | ||
- max-age=63072000 | ||
Vary: | ||
- Cookie, Origin, Accept-Language | ||
WWW-Authenticate: | ||
- Token | ||
X-CSRFToken: | ||
- 5dZg56rok3RheSgkWWqoIhnpkBNVnweDmGcAGv2FKNnwMYvc2KNsTDwm47CpDYZz | ||
X-Content-Type-Options: | ||
- nosniff | ||
X-Frame-Options: | ||
- DENY | ||
X-Session-Expires-In: | ||
- '300' | ||
status: | ||
code: 401 | ||
message: Unauthorized | ||
- request: | ||
body: null | ||
headers: | ||
Accept: | ||
- '*/*' | ||
Accept-Encoding: | ||
- gzip, deflate | ||
Connection: | ||
- keep-alive | ||
User-Agent: | ||
- python-requests/2.32.3 | ||
method: GET | ||
uri: https://open-forms.test.maykin.opengem.nl/api/v2/forms/9c65ab49-2635-4c8d-ac22-aaca67044a6c | ||
response: | ||
body: | ||
string: '{"type":"https://open-forms.test.maykin.opengem.nl/fouten/AuthenticationFailed/","code":"authentication_failed","title":"Ongeldige | ||
authenticatiegegevens.","status":401,"detail":"Ongeldige token.","instance":"urn:uuid:d545fdc9-8186-456a-999b-c0c388fe922a"}' | ||
headers: | ||
Allow: | ||
- GET, PUT, PATCH, DELETE, HEAD, OPTIONS | ||
Cache-Control: | ||
- max-age=0, no-cache, no-store, must-revalidate, private | ||
Connection: | ||
- keep-alive | ||
Content-Language: | ||
- nl | ||
Content-Length: | ||
- '255' | ||
Content-Type: | ||
- application/json | ||
Cross-Origin-Opener-Policy: | ||
- same-origin | ||
Date: | ||
- Wed, 31 Jul 2024 08:05:45 GMT | ||
Expires: | ||
- Wed, 31 Jul 2024 08:05:45 GMT | ||
Pragma: | ||
- no-cache | ||
Referrer-Policy: | ||
- same-origin | ||
Set-Cookie: | ||
- csrftoken=erCNNjLn8PKuLjVPK1ZDw3a4Rv7PUQS9; expires=Wed, 30 Jul 2025 08:05:45 | ||
GMT; Max-Age=31449600; Path=/; SameSite=None; Secure | ||
- openforms_sessionid=qm2mjv9kxo2xcckzvb0flhy5nt5d3zbz; expires=Wed, 31 Jul | ||
2024 08:10:45 GMT; HttpOnly; Max-Age=300; Path=/; SameSite=None; Secure | ||
Strict-Transport-Security: | ||
- max-age=63072000 | ||
Vary: | ||
- Cookie, Origin, Accept-Language | ||
WWW-Authenticate: | ||
- Token | ||
X-CSRFToken: | ||
- SDRW8cYDR5y2Ti1Ihv4D8Uns3RlWJ44eWUjzLlzQPK8murMnRmT6uNnmKciBtKMd | ||
X-Content-Type-Options: | ||
- nosniff | ||
X-Frame-Options: | ||
- DENY | ||
X-Session-Expires-In: | ||
- '300' | ||
status: | ||
code: 401 | ||
message: Unauthorized | ||
version: 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import pytest | ||
from decouple import config | ||
|
||
from openformsclient.client import Client | ||
|
||
API_ROOT = config("OFC_API_ROOT", "https://open-forms.test.maykin.opengem.nl/api/v2/") | ||
API_TOKEN = config("OFC_API_TOKEN", "hush-hush") | ||
|
||
|
||
@pytest.fixture | ||
def client(): | ||
return Client(api_root=API_ROOT, api_token=API_TOKEN, client_timeout=2) | ||
|
||
|
||
@pytest.fixture | ||
def bogus_client(): | ||
return Client(api_root=API_ROOT, api_token="bogus", client_timeout=2) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
test_form = { | ||
"uuid": "9c65ab49-2635-4c8d-ac22-aaca67044a6c", | ||
"name": "Open Inwoner ZGW Dev", | ||
"internalName": "", | ||
"slug": "open-inwoner-zgw-dev", | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,91 +1,73 @@ | ||
from unittest.mock import patch | ||
from urllib.parse import urljoin | ||
|
||
from django.test import TestCase | ||
|
||
import requests_mock | ||
import pytest | ||
import vcr | ||
from requests.exceptions import HTTPError | ||
|
||
from openformsclient.client import Client | ||
|
||
from .data.forms import test_form | ||
|
||
CASSETTE_PATH_FORMS = "fixtures/cassettes/forms.yaml" | ||
CASSETTE_PATH_INVALID = "fixtures/cassettes/invalid.yaml" | ||
VCR_DEFAULTS = { | ||
"record_mode": "none", # use new_episodes to record casettes | ||
"filter_headers": ["authorization"], | ||
} | ||
|
||
|
||
def test_client_has_config(client): | ||
bogus_client = Client("", "", "") | ||
|
||
assert client.has_config() | ||
assert not bogus_client.has_config() | ||
|
||
|
||
@vcr.use_cassette(CASSETTE_PATH_FORMS, **VCR_DEFAULTS) | ||
def test_client_is_healthy(client): | ||
health, msg = client.is_healthy() | ||
assert health | ||
assert msg == "" | ||
|
||
|
||
@vcr.use_cassette(CASSETTE_PATH_FORMS, **VCR_DEFAULTS) | ||
def test_get_forms(client): | ||
results = client.get_forms()["results"] | ||
|
||
assert test_form in results | ||
|
||
|
||
@vcr.use_cassette(CASSETTE_PATH_INVALID, **VCR_DEFAULTS) | ||
def test_get_forms_unauthorized(bogus_client): | ||
url = urljoin(bogus_client.api_root, "public/forms") | ||
msg = f"401 Client Error: Unauthorized for url: {url}" | ||
|
||
with pytest.raises(HTTPError, match=msg): | ||
bogus_client.get_forms() | ||
|
||
|
||
@vcr.use_cassette(CASSETTE_PATH_FORMS, **VCR_DEFAULTS) | ||
def test_get_single_form(client): | ||
result = client.get_form(uuid_or_slug=test_form["uuid"]) | ||
|
||
assert result["uuid"] == test_form["uuid"] | ||
assert result["name"] == test_form["name"] | ||
|
||
|
||
@vcr.use_cassette(CASSETTE_PATH_FORMS, **VCR_DEFAULTS) | ||
def test_get_single_form_not_found(client): | ||
bogus_uuid = "aaaa-bbbb-cccc-dddd" | ||
url = urljoin(client.api_root, f"forms/{bogus_uuid}") | ||
msg = f"404 Client Error: Not Found for url: {url}" | ||
|
||
with pytest.raises(HTTPError, match=msg): | ||
client.get_form(uuid_or_slug=bogus_uuid) | ||
|
||
|
||
@vcr.use_cassette(CASSETTE_PATH_INVALID, **VCR_DEFAULTS) | ||
def test_get_single_form_unauthorized(bogus_client): | ||
url = urljoin(bogus_client.api_root, f"forms/{test_form['uuid']}") | ||
msg = f"401 Client Error: Unauthorized for url: {url}" | ||
|
||
@requests_mock.Mocker() | ||
class ClientTests(TestCase): | ||
def setUp(self): | ||
self.api_root = "https://example.com/api/v2/" | ||
self.api_token = "token" | ||
self.client_timeout = 2 | ||
self.client = Client(self.api_root, self.api_token, self.client_timeout) | ||
|
||
def test_has_config(self, m): | ||
self.assertTrue(self.client.has_config()) | ||
self.assertFalse(Client("", "", "").has_config()) | ||
|
||
def test_is_healthy(self, m): | ||
m.head( | ||
f"{self.api_root}public/forms", | ||
request_headers={"Authorization": f"Token {self.api_token}"}, | ||
) | ||
|
||
health, msg = self.client.is_healthy() | ||
self.assertTrue(health) | ||
self.assertEqual(msg, "") | ||
|
||
def test_is_healthy_invalid_response(self, m): | ||
m.head(f"{self.api_root}public/forms", status_code=500) # Doesn't really matter | ||
m.get(f"{self.api_root}public/forms", text="Woops") | ||
|
||
health, msg = self.client.is_healthy() | ||
self.assertFalse(health) | ||
self.assertEqual(msg, "Server did not return a valid response (HTTP 500).") | ||
|
||
def test_is_healthy_invalid_token(self, m): | ||
m.head(f"{self.api_root}public/forms", status_code=401) | ||
m.get( | ||
f"{self.api_root}public/forms", | ||
json={ | ||
"type": "https://example.com/fouten/AuthenticationFailed/", | ||
"code": "authentication_failed", | ||
"title": "Ongeldige authenticatiegegevens.", | ||
"status": 401, | ||
"detail": "Ongeldige token.", | ||
"instance": "urn:uuid:8dddcb04-a412-451a-a7c5-f77d1aef36f5", | ||
}, | ||
) | ||
|
||
health, msg = self.client.is_healthy() | ||
self.assertFalse(health) | ||
self.assertEqual(msg, "Ongeldige token.") | ||
|
||
def test_get_forms(self, m): | ||
m.get(f"{self.api_root}public/forms", json=[]) | ||
|
||
result = self.client.get_forms() | ||
self.assertListEqual(result, []) | ||
|
||
def test_get_forms_with_error(self, m): | ||
m.get(f"{self.api_root}public/forms", status_code=401) | ||
|
||
with self.assertRaises(HTTPError): | ||
self.client.get_forms() | ||
|
||
def test_get_form(self, m): | ||
m.get(f"{self.api_root}forms/myform", json={}) | ||
|
||
result = self.client.get_form("myform") | ||
self.assertDictEqual(result, {}) | ||
|
||
def test_get_form_with_error(self, m): | ||
m.get(f"{self.api_root}forms/myform", status_code=401) | ||
|
||
with self.assertRaises(HTTPError): | ||
self.client.get_form("myform") | ||
|
||
def test_request_uses_configured_timeout(self, m): | ||
with patch("openformsclient.client.requests.request") as mock_request: | ||
self.client.get_form("myform") | ||
mock_request.assert_called_with( | ||
"get", | ||
"https://example.com/api/v2/forms/myform", | ||
headers={"Authorization": "Token token"}, | ||
timeout=2, | ||
) | ||
with pytest.raises(HTTPError, match=msg): | ||
bogus_client.get_form(uuid_or_slug=test_form["uuid"]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters