Skip to content

Commit 0b37272

Browse files
author
Joel Collins
committed
Improved decorators coverage
1 parent 5935f77 commit 0b37272

File tree

1 file changed

+211
-0
lines changed

1 file changed

+211
-0
lines changed

tests/test_server_decorators.py

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from labthings.server.schema import Schema
77
from labthings.server import fields
8+
from labthings.server.view import View
89
from labthings.core.tasks.thread import TaskThread
910

1011
from labthings.server import decorators
@@ -134,3 +135,213 @@ def test_safe(empty_cls):
134135
def test_idempotent(empty_cls):
135136
wrapped_cls = decorators.idempotent(empty_cls)
136137
assert wrapped_cls.__apispec__["_idempotent"] == True
138+
139+
140+
def test_thing_property(view_cls):
141+
wrapped_cls = decorators.thing_property(view_cls)
142+
assert wrapped_cls.__apispec__["tags"] == ["properties"]
143+
assert wrapped_cls.__apispec__["_groups"] == ["properties"]
144+
145+
146+
def test_thing_property_empty_class(empty_cls, app_ctx):
147+
wrapped_cls = decorators.thing_property(empty_cls)
148+
assert wrapped_cls.__apispec__["tags"] == ["properties"]
149+
assert wrapped_cls.__apispec__["_groups"] == ["properties"]
150+
151+
152+
def test_thing_property_property_notify(view_cls, app_ctx):
153+
wrapped_cls = decorators.thing_property(view_cls)
154+
155+
with app_ctx.test_request_context():
156+
wrapped_cls().post()
157+
158+
159+
def test_property_schema(app, client):
160+
class Index(View):
161+
def get(self):
162+
obj = type("obj", (object,), {"integer": 1})
163+
return obj
164+
165+
def post(self, args):
166+
i = args.get("integer")
167+
obj = type("obj", (object,), {"integer": i})
168+
return obj
169+
170+
def put(self, args):
171+
i = args.get("integer")
172+
obj = type("obj", (object,), {"integer": i})
173+
return obj
174+
175+
schema = _Schema.from_dict({"integer": fields.Int()})()
176+
WrappedCls = decorators.PropertySchema(schema)(Index)
177+
178+
assert WrappedCls.__apispec__.get("_propertySchema") == schema
179+
180+
app.add_url_rule("/", view_func=WrappedCls.as_view("index"))
181+
182+
with app.test_client() as c:
183+
assert c.get("/").data == b'{"integer":1}\n'
184+
assert c.post("/", json={"integer": 5}).data == b'{"integer":5}\n'
185+
assert c.put("/", json={"integer": 5}).data == b'{"integer":5}\n'
186+
187+
188+
def test_property_schema_empty_class(empty_cls):
189+
schema = _Schema.from_dict({"integer": fields.Int()})()
190+
WrappedCls = decorators.PropertySchema(schema)(empty_cls)
191+
192+
assert WrappedCls.__apispec__.get("_propertySchema") == schema
193+
194+
195+
def test_use_body(app, client):
196+
class Index(View):
197+
def post(self, data):
198+
return str(data)
199+
200+
schema = fields.Int()
201+
Index.post = decorators.use_body(schema)(Index.post)
202+
203+
assert Index.post.__apispec__.get("_params") == schema
204+
205+
app.add_url_rule("/", view_func=Index.as_view("index"))
206+
207+
with app.test_client() as c:
208+
assert c.post("/", data=b"5\n").data == b"5"
209+
210+
211+
def test_use_body_required_no_data(app, client):
212+
class Index(View):
213+
def post(self, data):
214+
return {}
215+
216+
schema = fields.Int(required=True)
217+
Index.post = decorators.use_body(schema)(Index.post)
218+
219+
assert Index.post.__apispec__.get("_params") == schema
220+
221+
app.add_url_rule("/", view_func=Index.as_view("index"))
222+
223+
with app.test_client() as c:
224+
assert c.post("/").status_code == 400
225+
226+
227+
def test_use_body_no_data(app, client):
228+
class Index(View):
229+
def post(self, data):
230+
assert data is None
231+
return {}
232+
233+
schema = fields.Int()
234+
Index.post = decorators.use_body(schema)(Index.post)
235+
236+
assert Index.post.__apispec__.get("_params") == schema
237+
238+
app.add_url_rule("/", view_func=Index.as_view("index"))
239+
240+
with app.test_client() as c:
241+
assert c.post("/").status_code == 200
242+
243+
244+
def test_use_body_no_data_missing_given(app, client):
245+
class Index(View):
246+
def post(self, data):
247+
return str(data)
248+
249+
schema = fields.Int(missing=5)
250+
Index.post = decorators.use_body(schema)(Index.post)
251+
252+
assert Index.post.__apispec__.get("_params") == schema
253+
254+
app.add_url_rule("/", view_func=Index.as_view("index"))
255+
256+
with app.test_client() as c:
257+
assert c.post("/").data == b"5"
258+
259+
260+
def test_use_body_malformed(app, client):
261+
class Index(View):
262+
def post(self, data):
263+
return {}
264+
265+
schema = fields.Int(required=True)
266+
Index.post = decorators.use_body(schema)(Index.post)
267+
268+
assert Index.post.__apispec__.get("_params") == schema
269+
270+
app.add_url_rule("/", view_func=Index.as_view("index"))
271+
272+
with app.test_client() as c:
273+
assert c.post("/", data=b"{}").status_code == 400
274+
275+
276+
def test_use_args(app, client):
277+
class Index(View):
278+
def post(self, data):
279+
return str(data)
280+
281+
schema = _Schema.from_dict({"integer": fields.Int()})()
282+
Index.post = decorators.use_args(schema)(Index.post)
283+
284+
assert Index.post.__apispec__.get("_params") == schema
285+
286+
app.add_url_rule("/", view_func=Index.as_view("index"))
287+
288+
with app.test_client() as c:
289+
assert c.post("/", json={"integer": 5}).data == b"{'integer': 5}"
290+
291+
292+
def test_use_args_field(app, client):
293+
class Index(View):
294+
def post(self, data):
295+
return str(data)
296+
297+
schema = fields.Int(missing=5)
298+
Index.post = decorators.use_args(schema)(Index.post)
299+
300+
assert Index.post.__apispec__.get("_params") == schema
301+
302+
app.add_url_rule("/", view_func=Index.as_view("index"))
303+
304+
with app.test_client() as c:
305+
assert c.post("/").data == b"5"
306+
307+
308+
def test_doc(empty_cls):
309+
wrapped_cls = decorators.doc(key="value")(empty_cls)
310+
assert wrapped_cls.__apispec__["key"] == "value"
311+
312+
313+
def test_tag(empty_cls):
314+
wrapped_cls = decorators.tag(["tag", "tag2"])(empty_cls)
315+
assert wrapped_cls.__apispec__["tags"] == ["tag", "tag2"]
316+
317+
318+
def test_tag_single(empty_cls):
319+
wrapped_cls = decorators.tag("tag")(empty_cls)
320+
assert wrapped_cls.__apispec__["tags"] == ["tag"]
321+
322+
323+
def test_tag_invalid(empty_cls):
324+
with pytest.raises(TypeError):
325+
decorators.tag(object())(empty_cls)
326+
327+
328+
def test_doc_response(empty_cls):
329+
wrapped_cls = decorators.doc_response(
330+
200, description="description", mimetype="text/plain", key="value"
331+
)(empty_cls)
332+
assert wrapped_cls.__apispec__ == {
333+
"responses": {
334+
200: {
335+
"description": "description",
336+
"key": "value",
337+
"content": {"text/plain": {}},
338+
}
339+
},
340+
"_content_type": "text/plain",
341+
}
342+
343+
344+
def test_doc_response_no_mimetype(empty_cls):
345+
wrapped_cls = decorators.doc_response(200)(empty_cls)
346+
assert wrapped_cls.__apispec__ == {"responses": {200: {"description": "OK"}}}
347+

0 commit comments

Comments
 (0)