-
Notifications
You must be signed in to change notification settings - Fork 437
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add infrastructure for test-helper methods (#773)
- Loading branch information
1 parent
5b0c253
commit 3c7be4b
Showing
5 changed files
with
151 additions
and
1 deletion.
There are no files selected for viewing
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 |
---|---|---|
|
@@ -58,3 +58,4 @@ venv.bak/ | |
!.vscode/tasks.json | ||
!.vscode/launch.json | ||
!.vscode/extensions.json | ||
/.idea |
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,77 @@ | ||
from __future__ import absolute_import, division, print_function | ||
|
||
from stripe import error, util, six | ||
from stripe.six.moves.urllib.parse import quote_plus | ||
from stripe.api_resources.abstract import APIResource | ||
|
||
|
||
class APIResourceTestHelpers: | ||
""" | ||
The base type for the TestHelper nested classes. | ||
Handles request URL generation for test_helper custom methods. | ||
Should be used in combination with the @test_helpers decorator. | ||
@test_helpers | ||
class Foo(APIResource): | ||
class TestHelpers(APIResourceTestHelpers): | ||
""" | ||
|
||
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,) | ||
|
||
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): | ||
""" | ||
test_helpers decorator adds a test_helpers property and | ||
wires the parent resource class to the nested TestHelpers class. | ||
Should only be used on types that inherit from APIResource. | ||
@test_helpers | ||
class Foo(APIResource): | ||
class TestHelpers(APIResourceTestHelpers): | ||
""" | ||
|
||
def test_helpers_getter(self): | ||
return self.TestHelpers(self) | ||
|
||
if not issubclass(cls, APIResource): | ||
raise ValueError( | ||
"Could not apply @test_helpers decorator to %r." | ||
" The class should a subclass of APIResource." % cls | ||
) | ||
|
||
cls.TestHelpers._resource_cls = cls | ||
cls.TestHelpers._static_request = cls._static_request | ||
cls.TestHelpers._static_request_stream = cls._static_request_stream | ||
|
||
cls.test_helpers = property(test_helpers_getter) | ||
return cls |
66 changes: 66 additions & 0 deletions
66
tests/api_resources/abstract/test_test_helpers_api_resource.py
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,66 @@ | ||
from __future__ import absolute_import, division, print_function | ||
|
||
import stripe | ||
import pytest | ||
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_via_property(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.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 | ||
|
||
def test_helper_decorator_raises_for_non_resource(self): | ||
with pytest.raises(ValueError): | ||
stripe.api_resources.abstract.test_helpers(str) |
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