Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add infrastructure for test-helper methods #773

Merged
merged 10 commits into from
Mar 25, 2022
Merged
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,4 @@ venv.bak/
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
/.idea
5 changes: 5 additions & 0 deletions stripe/api_resources/abstract/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@

from stripe.api_resources.abstract.custom_method import custom_method

from stripe.api_resources.abstract.test_helpers import (
test_helpers,
APIResourceTestHelpers,
)

from stripe.api_resources.abstract.nested_resource_class_methods import (
nested_resource_class_methods,
)
49 changes: 49 additions & 0 deletions stripe/api_resources/abstract/test_helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from __future__ import absolute_import, division, print_function

from stripe import error, util, six
from stripe.six.moves.urllib.parse import quote_plus


class APIResourceTestHelpers:
pakrym-stripe marked this conversation as resolved.
Show resolved Hide resolved
def __init__(self, resource):
self.resource = resource

@classmethod
def class_url(cls):
if cls == APIResourceTestHelpers:
raise NotImplementedError(
"APIResourceTestHelpers is an abstract class. You should perform "
"actions on its subclasses (e.g. Charge, Customer)"
)
# Namespaces are separated in object names with periods (.) and in URLs
# with forward slashes (/), so replace the former with the latter.
base = cls._resource_cls.OBJECT_NAME.replace(".", "/")
return "/v1/test_helpers/%ss" % (base,)
pakrym-stripe marked this conversation as resolved.
Show resolved Hide resolved

def instance_url(self):
id = self.resource.get("id")

if not isinstance(id, six.string_types):
raise error.InvalidRequestError(
"Could not determine which URL to request: %s instance "
"has invalid ID: %r, %s. ID should be of type `str` (or"
" `unicode`)" % (type(self).__name__, id, type(id)),
"id",
)

id = util.utf8(id)
base = self.class_url()
extn = quote_plus(id)
return "%s/%s" % (base, extn)


def test_helpers(cls):
pakrym-stripe marked this conversation as resolved.
Show resolved Hide resolved
def test_helpers_getter(self):
return self.TestHelpers(self)

cls.TestHelpers._resource_cls = cls
cls.TestHelpers._static_request = cls._static_request
cls.TestHelpers._static_request_stream = cls._static_request_stream
pakrym-stripe marked this conversation as resolved.
Show resolved Hide resolved

cls.test_helpers = property(test_helpers_getter)
return cls
61 changes: 61 additions & 0 deletions tests/api_resources/abstract/test_test_helpers_api_resource.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
from __future__ import absolute_import, division, print_function

import stripe
from stripe import util
from stripe.api_resources.abstract import APIResourceTestHelpers


class TestTestHelperAPIResource(object):
@stripe.api_resources.abstract.test_helpers
class MyTestHelpersResource(stripe.api_resources.abstract.APIResource):
OBJECT_NAME = "myresource"

@stripe.api_resources.abstract.custom_method(
"do_stuff", http_verb="post", http_path="do_the_thing"
)
class TestHelpers(APIResourceTestHelpers):
def __init__(self, resource):
self.resource = resource

def do_stuff(self, idempotency_key=None, **params):
url = self.instance_url() + "/do_the_thing"
headers = util.populate_headers(idempotency_key)
self.resource.refresh_from(
self.resource.request("post", url, params, headers)
)
return self.resource

def test_call_custom_method_class(self, request_mock):
request_mock.stub_request(
"post",
"/v1/test_helpers/myresources/mid/do_the_thing",
{"id": "mid", "thing_done": True},
rheaders={"request-id": "req_id"},
)

obj = self.MyTestHelpersResource.TestHelpers.do_stuff("mid", foo="bar")

request_mock.assert_requested(
"post",
"/v1/test_helpers/myresources/mid/do_the_thing",
{"foo": "bar"},
)
assert obj.thing_done is True

def test_call_custom_method_instance(self, request_mock):
pakrym-stripe marked this conversation as resolved.
Show resolved Hide resolved
request_mock.stub_request(
"post",
"/v1/test_helpers/myresources/mid/do_the_thing",
{"id": "mid", "thing_done": True},
rheaders={"request-id": "req_id"},
)

obj = self.MyTestHelpersResource.construct_from({"id": "mid"}, "mykey")
obj.test_helpers.do_stuff(foo="bar")

request_mock.assert_requested(
"post",
"/v1/test_helpers/myresources/mid/do_the_thing",
{"foo": "bar"},
)
assert obj.thing_done is True
3 changes: 2 additions & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ deps =
pytest-cov >= 2.8.1, < 2.11.0
pytest-mock >= 2.0.0
pytest-xdist >= 1.31.0
commands = pytest --cov {posargs:-n auto}
# ignore stripe directory as all tests are inside ./tests
commands = pytest --cov {posargs:-n auto} --ignore stripe
pakrym-stripe marked this conversation as resolved.
Show resolved Hide resolved
# compilation flags can be useful when prebuilt wheels cannot be used, e.g.
# PyPy 2 needs to compile the `cryptography` module. On macOS this can be done
# by passing the following flags:
Expand Down