Skip to content

Commit 5d5beaa

Browse files
committed
more tests
1 parent 9eea106 commit 5d5beaa

File tree

3 files changed

+149
-1
lines changed

3 files changed

+149
-1
lines changed

servicestack/servicestack.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
from datetime import datetime, date, timedelta
12
import json
3+
from servicestack.utils import to_timespan
24

35
from requests.models import HTTPError, Response
46

@@ -88,7 +90,16 @@ def clean_any(d):
8890
def _json_encoder(obj:Any):
8991
if is_dataclass(obj):
9092
return clean_any(asdict(obj))
91-
return vars(obj)
93+
if hasattr(obj,'__dict__'):
94+
return vars(obj)
95+
if isinstance(obj, (date, datetime)):
96+
return obj.isoformat()
97+
if isinstance(obj, timedelta):
98+
#a=timedelta(days=1,hours=1,minutes=1,seconds=1,milliseconds=1)
99+
return to_timespan(obj)
100+
if isinstance(obj, bytes):
101+
return base64.b64encode(obj).decode('ascii')
102+
raise TypeError(f"Unsupported Type in JSON encoding: {type(obj)}")
92103

93104
def json_encode(obj:Any):
94105
if is_dataclass(obj):

servicestack/utils.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from datetime import timedelta
2+
3+
def to_timespan(duration:timedelta):
4+
total_seconds = duration.total_seconds()
5+
whole_seconds = total_seconds // 1
6+
seconds = whole_seconds
7+
sec = seconds % 60 if seconds >= 60 else seconds
8+
seconds = seconds // 60
9+
min = seconds % 60
10+
seconds = seconds // 60
11+
hours = seconds % 60
12+
days = seconds // 24
13+
remaining_secs = float(sec + (total_seconds - whole_seconds))
14+
15+
sb=["P"]
16+
if days > 0:
17+
sb.append(f"{days}D")
18+
19+
if days == 0 or hours + min + sec + remaining_secs > 0:
20+
sb.append("T")
21+
if hours > 0:
22+
sb.append(f"{hours}H")
23+
if min > 0:
24+
sb.append(f"{min}M")
25+
26+
if remaining_secs > 0:
27+
sec_fmt = "{:.7f}".format(remaining_secs)
28+
sec_fmt = sec_fmt.rstrip('0')
29+
sec_fmt = sec_fmt.rstrip('.')
30+
sb.append(sec_fmt)
31+
sb.append("S")
32+
elif sb.count == 2: #PT
33+
sb.append("0S")
34+
35+
xsd = ''.join(sb)
36+
return xsd

tests/test_client.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from servicestack.servicestack import json_encode
66
import unittest
77
from .dtos import *
8+
from datetime import datetime, timedelta, timezone
89

910
from servicestack import JsonServiceClient
1011

@@ -13,10 +14,104 @@
1314
def create_test_client():
1415
return JsonServiceClient(TEST_URL)
1516

17+
def create_HelloAllTypes():
18+
return HelloAllTypes(name="name",
19+
all_types=create_AllTypes(),
20+
all_collection_types=create_AllCollectionTypes())
21+
22+
def create_AllTypes():
23+
return AllTypes(
24+
id=1,
25+
char='c',
26+
byte=2,
27+
short=3,
28+
int=4,
29+
long=5,
30+
u_short=6,
31+
u_int=7,
32+
u_long=8,
33+
float=1.1,
34+
double=2.2,
35+
decimal=3.0,
36+
string="string",
37+
date_time=datetime(2001,1,1, tzinfo=timezone.utc),
38+
date_time_offset=datetime(2001,1,1, tzinfo=timezone.utc),
39+
time_span=timedelta(hours=1),
40+
guid="ea762009b66c410b9bf5ce21ad519249",
41+
string_list=["A", "B", "C"],
42+
string_array=["D", "E", "F"],
43+
string_map={"A":"D","B":"E","C":"F"},
44+
int_string_map={1:"A",2:"B",3:"C"},
45+
sub_type=SubType(id=1,name="name"))
46+
47+
def create_AllCollectionTypes():
48+
return AllCollectionTypes(
49+
int_array=[1,2,3],
50+
int_list=[1,2,3],
51+
string_array=["A","B","C"],
52+
string_list=["D","E","F"],
53+
byte_array=b"QUJD", #base64(ABC)
54+
poco_array=[create_Poco("pocoArray")],
55+
poco_list=[create_Poco("pocoArray")],
56+
poco_lookup={"A":[create_Poco("B"),create_Poco("C")]},
57+
poco_lookup_map={"A":[{"B":create_Poco("C"),"D":create_Poco("E")}]})
58+
59+
def create_Poco(name:str): return Poco(name=name)
60+
1661
client = create_test_client()
1762

1863
class TestApi(unittest.TestCase):
1964

65+
def assert_HelloAllTypesResponse(self,dto:HelloAllTypesResponse):
66+
self.assertEqual(dto.result,"name")
67+
self.assert_AllTypes(dto.all_types)
68+
self.assert_AllCollectionTypes(dto.all_collection_types)
69+
70+
def assert_AllTypes(self,dto:AllTypes):
71+
self.assertEqual(dto.id,1)
72+
self.assertEqual(dto.byte,2)
73+
self.assertEqual(dto.short,3)
74+
self.assertEqual(dto.int,4)
75+
self.assertEqual(dto.long,5)
76+
self.assertEqual(dto.u_short,6)
77+
self.assertEqual(dto.u_int,7)
78+
self.assertEqual(dto.u_long,8)
79+
self.assertEqual(dto.float,1.1)
80+
self.assertEqual(dto.double,2.2)
81+
self.assertEqual(dto.decimal,3.0)
82+
self.assertEqual(dto.string,"string")
83+
self.assertEqual(dto.date_time,datetime(2001,1,1, tzinfo=timezone.utc))
84+
self.assertEqual(dto.date_time_offset,datetime(2001,1,1, tzinfo=timezone.utc))
85+
self.assertEqual(dto.time_span,timedelta(hours=1))
86+
self.assertEqual(dto.guid,"ea762009b66c410b9bf5ce21ad519249")
87+
self.assertListEqual(dto.string_list,["A", "B", "C"])
88+
self.assertListEqual(dto.string_array,["D", "E", "F"])
89+
self.assertDictEqual(dto.string_map,{"A":"D","B":"E","C":"F"})
90+
self.assertDictEqual(dto.int_string_map,{1:"A",2:"B",3:"C"})
91+
self.assertEqual(dto.sub_type.id,1)
92+
self.assertEqual(dto.sub_type.name,"name")
93+
94+
def assert_AllCollectionTypes(self,dto:AllCollectionTypes):
95+
self.assertListEqual(dto.int_array,[1,2,3])
96+
self.assertListEqual(dto.int_list,[1,2,3])
97+
self.assertListEqual(dto.string_array,["A","B","C"])
98+
self.assertListEqual(dto.string_list,["A","B","C"])
99+
self.assertEqual(dto.byte_array,b'ABC')
100+
self.assertEqual(dto.poco_array.count,1)
101+
self.assertEqual(dto.poco_array[0].name,"pocoArray")
102+
self.assertEqual(len(dto.poco_lookup),1)
103+
poco_lookup_values=dto.poco_lookup["A"]
104+
self.assertEqual(poco_lookup_values.count,2)
105+
self.assertEqual(poco_lookup_values[0].name,"B")
106+
self.assertEqual(poco_lookup_values[1].name,"C")
107+
self.assertEqual(len(dto.poco_lookup_map),1)
108+
poco_lookup_map_values=dto.poco_lookup_map["A"]
109+
self.assertEqual(poco_lookup_map_values.count,1)
110+
poco_lookup_mapa_list=poco_lookup_map_values[0]
111+
self.assertEqual(len(poco_lookup_mapa_list),2)
112+
self.assertEqual(poco_lookup_mapa_list["B"].name,"C")
113+
self.assertEqual(poco_lookup_mapa_list["D"].name,"E")
114+
20115
def test_can_get_hello(self):
21116
response:HelloResponse = client.get(Hello(name="World"))
22117
self.assertEqual(response.result, "Hello, World!")
@@ -75,3 +170,9 @@ def test_can_post_hello_with_CustomPath_json_object(self):
75170
self.assertIsInstance(json_obj, dict)
76171
response = HelloResponse(**json_obj)
77172
self.assertEqual(response.result, "Hello, World!")
173+
174+
def test_can_post_HelloAllTypes(self):
175+
request=create_HelloAllTypes()
176+
response:HelloAllTypesResponse=client.post(request)
177+
self.assert_HelloAllTypesResponse(response)
178+

0 commit comments

Comments
 (0)