-
-
Notifications
You must be signed in to change notification settings - Fork 291
Expand file tree
/
Copy pathtest_coinbase.py
More file actions
115 lines (90 loc) · 3.08 KB
/
Copy pathtest_coinbase.py
File metadata and controls
115 lines (90 loc) · 3.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
from __future__ import annotations
import hashlib
import json
from decimal import Decimal
from unittest.mock import MagicMock
from unittest.mock import patch
import pytest
from django.http import HttpResponse
from django.http import HttpResponseForbidden
from payments import PaymentStatus
from payments import PurchasedItem
from . import CoinbaseProvider
PAYMENT_TOKEN = "5a4dae68-2715-4b1e-8bb2-2c2dbe9255f6"
KEY = "abc123"
SECRET = "123abc"
VARIANT = "coinbase"
COINBASE_REQUEST = {
"order": {
"transaction": {"id": "123456"},
"custom": hashlib.md5((f"coinbase-{PAYMENT_TOKEN}-{KEY}").encode()).hexdigest(),
}
}
class Payment:
id = 1
description = "payment"
currency = "BTC"
total = Decimal(100)
status = PaymentStatus.WAITING
token = PAYMENT_TOKEN
variant = VARIANT
def change_status(self, status: str) -> None:
self.status = status
def get_failure_url(self) -> str:
return "http://cancel.com"
def get_process_url(self) -> str:
return "http://example.com"
def get_purchased_items(self) -> list[PurchasedItem]:
return []
def save(self) -> Payment:
return self
def get_success_url(self) -> str:
return "http://success.com"
@pytest.fixture
def provider() -> tuple[Payment, CoinbaseProvider]:
payment = Payment()
return payment, CoinbaseProvider(key=KEY, secret=SECRET)
def test_process_data(provider: tuple[Payment, CoinbaseProvider]) -> None:
payment, prov = provider
request = MagicMock()
request.body = json.dumps(COINBASE_REQUEST)
response = prov.process_data(payment, request)
assert isinstance(response, HttpResponse)
assert payment.status == PaymentStatus.CONFIRMED
def test_incorrect_custom_token_process_data(
provider: tuple[Payment, CoinbaseProvider],
) -> None:
payment, prov = provider
data = dict(COINBASE_REQUEST)
data.update({"order": {"custom": "fake"}})
request = MagicMock()
request.body = json.dumps(data)
response = prov.process_data(payment, request)
assert isinstance(response, HttpResponseForbidden)
def test_incorrect_data_process_data(
provider: tuple[Payment, CoinbaseProvider],
) -> None:
payment, prov = provider
request = MagicMock()
request.POST = {"id": "1234"}
response = prov.process_data(payment, request)
assert isinstance(response, HttpResponseForbidden)
@patch("time.time")
@patch("requests.post")
def test_provider_returns_checkout_url(
mocked_post: MagicMock,
mocked_time: MagicMock,
provider: tuple[Payment, CoinbaseProvider],
) -> None:
payment, prov = provider
code = "123abc"
signature = "21d476eff7b2e6cccdfe6deb0c097ba638d5de7e775b303e4fdb2f8bfeff72e2"
url = f"https://sandbox.coinbase.com/checkouts/{code}"
post = MagicMock()
post.json = MagicMock(return_value={"button": {"code": code}})
post.status_code = 200
mocked_post.return_value = post
mocked_time.return_value = 1
form = prov.get_form(payment)
assert form.action == url
assert mocked_post.call_args[1]["headers"]["ACCESS_SIGNATURE"] == signature