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
2 changes: 2 additions & 0 deletions stripe/api_resources/abstract/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@

from stripe.api_resources.abstract.custom_method import custom_method

from stripe.api_resources.abstract.test_helpers import test_helpers

from stripe.api_resources.abstract.nested_resource_class_methods import (
nested_resource_class_methods,
)
21 changes: 17 additions & 4 deletions stripe/api_resources/abstract/custom_method.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,23 @@ def custom_method(name, http_verb, http_path=None, is_streaming=False):
http_path = name

def wrapper(cls):
# Custom method can be defined on the resource class or TestHelpers class
# In TestHelpers case, the _resource_cls attribute will contain the
# resource implementation
def get_resource_class(cls):
resource_cls = getattr(cls, "_resource_cls", None)
if resource_cls is None:
resource_cls = cls
return resource_cls

def custom_method_request(cls, sid, **params):
resource_cls = get_resource_class(cls)
url = "%s/%s/%s" % (
cls.class_url(),
resource_cls.class_url(),
quote_plus(util.utf8(sid)),
http_path,
)
obj = cls._static_request(http_verb, url, **params)
obj = resource_cls._static_request(http_verb, url, **params)

# For list objects, we have to attach the parameters so that they
# can be referenced in auto-pagination and ensure consistency.
Expand All @@ -30,12 +40,15 @@ def custom_method_request(cls, sid, **params):
return obj

def custom_method_request_stream(cls, sid, **params):
resource_cls = get_resource_class(cls)
url = "%s/%s/%s" % (
cls.class_url(),
resource_cls.class_url(),
quote_plus(util.utf8(sid)),
http_path,
)
return cls._static_request_stream(http_verb, url, **params)
return resource_cls._static_request_stream(
http_verb, url, **params
)

if is_streaming:
class_method_impl = classmethod(custom_method_request_stream)
Expand Down
10 changes: 10 additions & 0 deletions stripe/api_resources/abstract/test_helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from __future__ import absolute_import, division, print_function


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.test_helpers = property(test_helpers_getter)
return cls
56 changes: 56 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,56 @@
from __future__ import absolute_import, division, print_function

import stripe
from stripe import util


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:
def __init__(self, resource):
self.resource = resource

def do_stuff(self, idempotency_key=None, **params):
url = self.resource.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/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/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/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/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