Skip to content

Commit

Permalink
Merge pull request #148 from maxmind/sromani/remove-mocket
Browse files Browse the repository at this point in the history
Remove mocket
  • Loading branch information
oschwald authored Jul 17, 2024
2 parents 0b86283 + 65627ff commit f65ddfd
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 69 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ jobs:

strategy:
matrix:
# We don't test on Windows currently as it appears mocket may not
# work there.
# TODO: add windows-latest
platform: [ubuntu-latest, macos-latest]
python-version: [3.8, 3.9, "3.10", 3.11, 3.12]

Expand Down
5 changes: 3 additions & 2 deletions minfraud/webservice.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@

_REQUEST_UA = f"minFraud-API/{__version__} {requests.utils.default_user_agent()}"

_SCHEME = "https"


# pylint: disable=too-many-instance-attributes, missing-class-docstring
class BaseClient:
Expand All @@ -57,8 +59,7 @@ def __init__(
self._account_id = str(account_id)
self._license_key = license_key
self._timeout = timeout

base_uri = f"https://{host}/minfraud/v2.0"
base_uri = f"{_SCHEME}://{host}/minfraud/v2.0"
self._score_uri = "/".join([base_uri, "score"])
self._insights_uri = "/".join([base_uri, "insights"])
self._factors_uri = "/".join([base_uri, "factors"])
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ classifiers = [

[project.optional-dependencies]
test = [
"mocket>=3.12.8",
"pytest-httpserver>=1.0.10",
]

[tool.setuptools.package-data]
Expand Down
4 changes: 3 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ python =

[testenv:{py38,py39,py310,py311,py312}-test]
deps =
mocket
pytest-httpserver
pytest

commands = pytest tests
Expand All @@ -35,6 +35,8 @@ commands = flake8 minfraud
[testenv:py312-mypy]
deps =
mypy
pytest_httpserver
pytest
types-requests
voluptuous-stubs
commands = mypy minfraud tests
113 changes: 50 additions & 63 deletions tests/test_webservice.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@
import os
from io import open
from typing import Type, Union

# httpretty currently doesn't work, but mocket with the compat interface
# does. See, e.g., https://github.com/gabrielfalcao/HTTPretty/issues/220
from mocket.plugins.httpretty import httpretty, httprettified # type: ignore
from pytest_httpserver import HTTPServer
import pytest

from minfraud.errors import (
HTTPError,
Expand All @@ -19,15 +17,25 @@
from minfraud.models import Factors, Insights, Score
from minfraud.webservice import AsyncClient, Client

import minfraud.webservice
import unittest

minfraud.webservice._SCHEME = "http"


class BaseTest(unittest.TestCase):
client_class: Union[Type[AsyncClient], Type[Client]] = Client

def setUp(self):
self.client = self.client_class(42, "abcdef123456")
@pytest.fixture(autouse=True)
def setup_httpserver(self, httpserver: HTTPServer):
self.httpserver = httpserver

def setUp(self):
self.client = self.client_class(
42,
"abcdef123456",
host="{0}:{1}".format(self.httpserver.host, self.httpserver.port),
)
test_dir = os.path.join(os.path.dirname(__file__), "data")
with open(os.path.join(test_dir, self.request_file), encoding="utf-8") as file:
content = file.read()
Expand All @@ -36,9 +44,6 @@ def setUp(self):
with open(os.path.join(test_dir, self.response_file), encoding="utf-8") as file:
self.response = file.read()

base_uri = "https://minfraud.maxmind.com/minfraud/v2.0"

@httprettified
def test_invalid_auth(self):
for error in (
"ACCOUNT_ID_REQUIRED",
Expand All @@ -52,27 +57,23 @@ def test_invalid_auth(self):
status_code=401,
)

@httprettified
def test_invalid_request(self):
with self.assertRaisesRegex(InvalidRequestError, "IP invalid"):
self.create_error(text='{"code":"IP_ADDRESS_INVALID","error":"IP invalid"}')

@httprettified
def test_300_error(self):
with self.assertRaisesRegex(
HTTPError, r"Received an unexpected HTTP status \(300\) for"
):
self.create_error(status_code=300)

@httprettified
def test_permission_required(self):
with self.assertRaisesRegex(PermissionRequiredError, "permission"):
self.create_error(
text='{"code":"PERMISSION_REQUIRED","error":"permission required"}',
status_code=403,
)

@httprettified
def test_400_with_invalid_json(self):
with self.assertRaisesRegex(
HTTPError,
Expand All @@ -81,19 +82,16 @@ def test_400_with_invalid_json(self):
):
self.create_error(text="{blah}")

@httprettified
def test_400_with_no_body(self):
with self.assertRaisesRegex(HTTPError, "Received a 400 error with no body"):
self.create_error()

@httprettified
def test_400_with_unexpected_content_type(self):
with self.assertRaisesRegex(
HTTPError, "Received a 400 with the following body: b?'?plain'?"
):
self.create_error(content_type="text/plain", text="plain")

@httprettified
def test_400_without_json_body(self):
with self.assertRaisesRegex(
HTTPError,
Expand All @@ -102,7 +100,6 @@ def test_400_without_json_body(self):
):
self.create_error(text="plain")

@httprettified
def test_400_with_unexpected_json(self):
with self.assertRaisesRegex(
HTTPError,
Expand All @@ -111,55 +108,53 @@ def test_400_with_unexpected_json(self):
):
self.create_error(text='{"not":"expected"}')

@httprettified
def test_500_error(self):
with self.assertRaisesRegex(HTTPError, r"Received a server error \(500\) for"):
self.create_error(status_code=500)

def create_error(self, status_code=400, text="", content_type=None):
uri = "/".join(
[self.base_uri, "transactions", "report"]
["/minfraud/v2.0", "transactions", "report"]
if self.type == "report"
else [self.base_uri, self.type]
else ["/minfraud/v2.0", self.type]
)
if content_type is None:
content_type = (
"application/json"
if self.type == "report"
else "application/vnd.maxmind.com-error+json; charset=UTF-8; version=2.0"
)
httpretty.register_uri(
httpretty.POST,
uri=uri,
status=status_code,
body=text,
self.httpserver.expect_request(uri, method="POST").respond_with_data(
text,
content_type=content_type,
status=status_code,
)
return self.run_client(getattr(self.client, self.type)(self.full_request))

def create_success(self, text=None, client=None, request=None):
uri = "/".join(
[self.base_uri, "transactions", "report"]
["/minfraud/v2.0", "transactions", "report"]
if self.type == "report"
else [self.base_uri, self.type]
else ["/minfraud/v2.0", self.type]
)
httpretty.register_uri(
httpretty.POST,
uri=uri,
status=204 if self.type == "report" else 200,
body=self.response if text is None else text,
if request is None:
request = self.full_request

response = self.response if text is None else text
status = 204 if self.type == "report" else 200
self.httpserver.expect_request(uri, method="POST").respond_with_data(
response,
content_type=f"application/vnd.maxmind.com-minfraud-{self.type}+json; charset=UTF-8; version=2.0",
status=status,
)
if client is None:
client = self.client
if request is None:
request = self.full_request

return self.run_client(getattr(client, self.type)(request))

def run_client(self, v):
return v

@httprettified
def test_named_constructor_args(self):
id = "47"
key = "1234567890ab"
Expand All @@ -170,7 +165,6 @@ def test_named_constructor_args(self):
self.assertEqual(client._account_id, id)
self.assertEqual(client._license_key, key)

@httprettified
def test_missing_constructor_args(self):
with self.assertRaises(TypeError):
self.client_class(license_key="1234567890ab")
Expand All @@ -180,10 +174,10 @@ def test_missing_constructor_args(self):


class BaseTransactionTest(BaseTest):

def has_ip_location(self):
return self.type in ["factors", "insights"]

@httprettified
def test_200(self):
model = self.create_success()
response = json.loads(self.response)
Expand All @@ -197,7 +191,6 @@ def test_200(self):
self.assertEqual("004", model.ip_address.traits.mobile_network_code)
self.assertEqual("ANONYMOUS_IP", model.ip_address.risk_reasons[0].code)

@httprettified
def test_200_on_request_with_nones(self):
model = self.create_success(
request={
Expand All @@ -215,36 +208,36 @@ def test_200_on_request_with_nones(self):
response = self.response
self.assertEqual(0.01, model.risk_score)

@httprettified
def test_200_with_email_hashing(self):
uri = "/".join([self.base_uri, self.type])

httpretty.register_uri(
httpretty.POST,
uri=uri,
status=200,
body=self.response,
content_type=f"application/vnd.maxmind.com-minfraud-{self.type}+json; charset=UTF-8; version=2.0",
)

request = {"email": {"address": "[email protected]"}}
self.run_client(getattr(self.client, self.type)(request, hash_email=True))

self.assertEqual(
{
uri = "/".join(["/minfraud/v2.0", self.type])
self.httpserver.expect_request(
uri,
method="POST",
json={
"email": {
"address": "977577b140bfb7c516e4746204fbdb01",
"domain": "maxmind.com",
}
},
json.loads(httpretty.last_request.body),
).respond_with_data(
self.response,
content_type=f"application/vnd.maxmind.com-minfraud-{self.type}+json; charset=UTF-8; version=2.0",
status=200,
)

request = {"email": {"address": "[email protected]"}}
self.run_client(getattr(self.client, self.type)(request, hash_email=True))

# This was fixed in https://github.com/maxmind/minfraud-api-python/pull/78
@httprettified

def test_200_with_locales(self):
locales = ("fr",)
client = self.client_class(42, "abcdef123456", locales=locales)
client = self.client_class(
42,
"abcdef123456",
locales=locales,
host="{0}:{1}".format(self.httpserver.host, self.httpserver.port),
)
model = self.create_success(client=client)
response = json.loads(self.response)
if self.has_ip_location():
Expand All @@ -254,7 +247,6 @@ def test_200_with_locales(self):
self.assertEqual("Royaume-Uni", model.ip_address.country.name)
self.assertEqual("Londres", model.ip_address.city.name)

@httprettified
def test_200_with_reserved_ip_warning(self):
model = self.create_success(
"""
Expand All @@ -275,7 +267,6 @@ def test_200_with_reserved_ip_warning(self):

self.assertEqual(12, model.risk_score)

@httprettified
def test_200_with_no_body(self):
with self.assertRaisesRegex(
MinFraudError,
Expand All @@ -284,7 +275,6 @@ def test_200_with_no_body(self):
):
self.create_success(text="")

@httprettified
def test_200_with_invalid_json(self):
with self.assertRaisesRegex(
MinFraudError,
Expand All @@ -293,7 +283,6 @@ def test_200_with_invalid_json(self):
):
self.create_success(text="{")

@httprettified
def test_insufficient_funds(self):
with self.assertRaisesRegex(InsufficientFundsError, "out of funds"):
self.create_error(
Expand Down Expand Up @@ -328,11 +317,9 @@ class TestReportTransaction(BaseTest):
request_file = "full-report-request.json"
response_file = "report-response.json"

@httprettified
def test_204(self):
self.create_success()

@httprettified
def test_204_on_request_with_nones(self):
self.create_success(
request={
Expand Down

0 comments on commit f65ddfd

Please sign in to comment.