Skip to content

Commit a3d0773

Browse files
committed
Add integration tests
1 parent ada1195 commit a3d0773

23 files changed

+2464
-0
lines changed

tests/integration/__init__.py

Whitespace-only changes.

tests/integration/helpers.py

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
import os
2+
import uuid
3+
from datetime import datetime
4+
from typing import List
5+
6+
from square import Square
7+
from square.core import File
8+
from square.environment import SquareEnvironment
9+
from square.types.address import Address
10+
from square.types.catalog_item import CatalogItem
11+
from square.types.catalog_item_variation import CatalogItemVariation
12+
from square.types.catalog_object import CatalogObject
13+
from square.types.catalog_object_item import CatalogObjectItem
14+
from square.types.catalog_object_item_variation import CatalogObjectItemVariation
15+
from square.types.location import Location
16+
from square.types.money import Money
17+
18+
19+
class CreateCatalogItemVariationOptions:
20+
name: str
21+
price_money: Money
22+
23+
def __init__(self):
24+
self.name = "Variation " + str(uuid.uuid4())
25+
self.price_money = new_test_money(1000)
26+
27+
def variation(self) -> CatalogItemVariation:
28+
return CatalogItemVariation(
29+
name=self.name,
30+
track_inventory=True,
31+
pricing_type="FIXED_PRICING",
32+
price_money=self.price_money,
33+
)
34+
35+
36+
class CreateCatalogItemOptions:
37+
name: str
38+
description: str
39+
abbreviation: str
40+
variation_opts: List[CreateCatalogItemVariationOptions]
41+
42+
def __init__(self):
43+
self.name = "Item " + str(uuid.uuid4())
44+
self.description = "Test item description"
45+
self.abbreviation = "TST"
46+
self.variation_opts = [CreateCatalogItemVariationOptions()]
47+
48+
def variations(self) -> List[CatalogObject]:
49+
return [
50+
CatalogObjectItemVariation(
51+
type="ITEM_VARIATION",
52+
id="#variation" + str(uuid.uuid4()),
53+
present_at_all_locations=True,
54+
item_variation_data=opts.variation(),
55+
)
56+
for opts in self.variation_opts
57+
]
58+
59+
60+
def test_client() -> Square:
61+
return Square(
62+
token=os.getenv("TEST_SQUARE_TOKEN"),
63+
environment=SquareEnvironment.SANDBOX,
64+
)
65+
66+
67+
def new_test_money(amount: int) -> Money:
68+
return Money(amount=amount, currency="USD")
69+
70+
71+
def create_test_catalog_item(opts: CreateCatalogItemOptions) -> CatalogObject:
72+
return CatalogObjectItem(
73+
type="ITEM",
74+
id="#" + str(uuid.uuid4()),
75+
present_at_all_locations=True,
76+
item_data=CatalogItem(
77+
name=opts.name,
78+
description=opts.description,
79+
abbreviation=opts.abbreviation,
80+
variations=opts.variations(),
81+
),
82+
)
83+
84+
85+
def get_test_file() -> File:
86+
with open("tests/integration/testdata/image.jpeg", "rb") as file:
87+
return file.read()
88+
89+
90+
def create_location(client: Square) -> str:
91+
locations_response = client.locations.create(
92+
location={"name": "Test location " + str(uuid.uuid4())}
93+
)
94+
95+
location = locations_response.location
96+
if location is None or not isinstance(location, Location):
97+
raise Exception("Could not get location.")
98+
location_id = location.id
99+
if location_id is None:
100+
raise Exception("Could not get location ID.")
101+
return location_id
102+
103+
104+
def create_test_customer(client: Square) -> str:
105+
address = test_address()
106+
response = client.customers.create(
107+
idempotency_key=str(uuid.uuid4()),
108+
given_name="Amelia",
109+
family_name="Earhart",
110+
phone_number="1-212-555-4240",
111+
note="test customer",
112+
address={
113+
"address_line1": address.address_line1,
114+
"address_line2": address.address_line2,
115+
"locality": address.locality,
116+
"administrative_district_level1": address.administrative_district_level1,
117+
"postal_code": address.postal_code,
118+
"country": address.country,
119+
},
120+
)
121+
customer = response.customer
122+
if customer is None:
123+
raise Exception("Could not get customer.")
124+
customer_id = customer.id
125+
if customer_id is None:
126+
raise Exception("Could not get customer ID.")
127+
return customer_id
128+
129+
130+
def test_address() -> Address:
131+
return Address(
132+
address_line1="500 Electric Ave",
133+
address_line2="Suite 600A",
134+
locality="New York",
135+
administrative_district_level1="NY",
136+
postal_code="10003",
137+
country="US",
138+
)
139+
140+
141+
def get_default_location_id(client: Square) -> str:
142+
response = client.locations.list()
143+
locations = response.locations
144+
if locations is None or len(locations) == 0:
145+
raise Exception("Could not get locations.")
146+
location_id = locations[0].id
147+
if location_id is None:
148+
raise Exception("Could not get location ID.")
149+
return location_id
150+
151+
152+
def new_test_square_id() -> str:
153+
return "#" + str(uuid.uuid4())
154+
155+
156+
def format_date_string(date: datetime) -> str:
157+
return date.isoformat()[:19] + "Z"
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
from square.core.api_error import ApiError
2+
from square.types.error import Error
3+
4+
5+
class TestResponse:
6+
def __init__(self, data):
7+
for key, value in data.items():
8+
if isinstance(value, list):
9+
setattr(
10+
self,
11+
key,
12+
[
13+
TestResponse(item) if isinstance(item, dict) else item
14+
for item in value
15+
],
16+
)
17+
else:
18+
setattr(self, key, value)
19+
20+
21+
def test_exception_without_body():
22+
exception = ApiError(status_code=400, body=None)
23+
24+
assert "status_code: 400" in str(exception)
25+
assert exception.status_code == 400
26+
assert len(exception.errors) == 1
27+
assert isinstance(exception.errors[0], Error)
28+
assert exception.errors[0].code == "Unknown"
29+
assert exception.errors[0].category == "API_ERROR"
30+
assert exception.errors[0].field is None
31+
assert exception.errors[0].detail is None
32+
33+
34+
def test_exception_with_v1_error():
35+
error_string = """{
36+
"type": "INVALID_REQUEST",
37+
"message": "Invalid field value",
38+
"field": "customer_id"
39+
}"""
40+
exception = ApiError(status_code=400, body=error_string)
41+
42+
assert "status_code: 400" in str(exception)
43+
assert "body:" in str(exception)
44+
assert exception.status_code == 400
45+
assert len(exception.errors) == 1
46+
assert isinstance(exception.errors[0], Error)
47+
assert exception.errors[0].code == "INVALID_REQUEST"
48+
assert exception.errors[0].category == "API_ERROR"
49+
assert exception.errors[0].field == "customer_id"
50+
assert exception.errors[0].detail == "Invalid field value"
51+
52+
53+
def test_exception_with_v1_error_without_type():
54+
error_string = """{
55+
"message": "Invalid field value",
56+
"field": "customer_id"
57+
}"""
58+
exception = ApiError(status_code=400, body=error_string)
59+
60+
assert "status_code: 400" in str(exception)
61+
assert exception.status_code == 400
62+
assert len(exception.errors) == 1
63+
assert isinstance(exception.errors[0], Error)
64+
assert exception.errors[0].code == "Unknown"
65+
assert exception.errors[0].category == "API_ERROR"
66+
assert exception.errors[0].field == "customer_id"
67+
assert exception.errors[0].detail == "Invalid field value"
68+
69+
70+
def test_exception_with_v2_error():
71+
error_string = """{
72+
"errors": [{
73+
"category": "API_ERROR",
74+
"code": "BAD_REQUEST",
75+
"detail": "Invalid input",
76+
"field": "email"
77+
}]
78+
}"""
79+
exception = ApiError(status_code=400, body=error_string)
80+
81+
assert "status_code: 400" in str(exception)
82+
assert exception.status_code == 400
83+
assert len(exception.errors) == 1
84+
assert isinstance(exception.errors[0], Error)
85+
assert exception.errors[0].category == "API_ERROR"
86+
assert exception.errors[0].code == "BAD_REQUEST"
87+
assert exception.errors[0].detail == "Invalid input"
88+
assert exception.errors[0].field == "email"
89+
90+
91+
def test_exception_with_v2_error_as_dict():
92+
errors = {
93+
"errors": [
94+
{
95+
"category": "API_ERROR",
96+
"code": "BAD_REQUEST",
97+
"detail": "Invalid input",
98+
"field": "email",
99+
}
100+
]
101+
}
102+
exception = ApiError(status_code=400, body=errors)
103+
104+
assert "status_code: 400" in str(exception)
105+
assert exception.status_code == 400
106+
assert len(exception.errors) == 1
107+
assert isinstance(exception.errors[0], Error)
108+
assert exception.errors[0].category == "API_ERROR"
109+
assert exception.errors[0].code == "BAD_REQUEST"
110+
assert exception.errors[0].detail == "Invalid input"
111+
assert exception.errors[0].field == "email"
112+
113+
114+
def test_exception_with_v2_error_as_object():
115+
errors = TestResponse(
116+
{
117+
"errors": [
118+
{
119+
"category": "API_ERROR",
120+
"code": "BAD_REQUEST",
121+
"detail": "Invalid input",
122+
"field": "email",
123+
}
124+
]
125+
}
126+
)
127+
128+
exception = ApiError(status_code=400, body=errors)
129+
130+
assert "status_code: 400" in str(exception)
131+
assert exception.status_code == 400
132+
assert len(exception.errors) == 1
133+
assert isinstance(exception.errors[0], Error)
134+
assert exception.errors[0].category == "API_ERROR"
135+
assert exception.errors[0].code == "BAD_REQUEST"
136+
assert exception.errors[0].detail == "Invalid input"
137+
assert exception.errors[0].field == "email"
138+
139+
140+
def test_exception_with_multiple_errors():
141+
errors = {
142+
"errors": [
143+
{
144+
"category": "API_ERROR",
145+
"code": "BAD_REQUEST",
146+
"detail": "Invalid input",
147+
"field": "email",
148+
},
149+
{
150+
"category": "AUTHENTICATION_ERROR",
151+
"code": "UNAUTHORIZED",
152+
"detail": "Not authorized",
153+
"field": None,
154+
},
155+
]
156+
}
157+
exception = ApiError(status_code=400, body=errors)
158+
159+
assert exception.status_code == 400
160+
assert len(exception.errors) == 2
161+
162+
# First error
163+
assert exception.errors[0].category == "API_ERROR"
164+
assert exception.errors[0].code == "BAD_REQUEST"
165+
assert exception.errors[0].detail == "Invalid input"
166+
assert exception.errors[0].field == "email"
167+
168+
# Second error
169+
assert exception.errors[1].category == "AUTHENTICATION_ERROR"
170+
assert exception.errors[1].code == "UNAUTHORIZED"
171+
assert exception.errors[1].detail == "Not authorized"
172+
assert exception.errors[1].field is None
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from datetime import datetime, timedelta
2+
3+
from . import helpers
4+
5+
6+
def test_list_cash_drawer_shifts():
7+
client = helpers.test_client()
8+
begin_time = (datetime.now() - timedelta(seconds=1)).isoformat()
9+
end_time = datetime.now().isoformat()
10+
location_id = helpers.get_default_location_id(client)
11+
12+
response = client.cash_drawers.shifts.list(
13+
location_id=location_id, begin_time=begin_time, end_time=end_time
14+
)
15+
16+
assert response is not None

0 commit comments

Comments
 (0)