Skip to content

Commit f0b8f48

Browse files
author
Joel Collins
committed
Updated tests for new structure
1 parent 74c1db1 commit f0b8f48

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+4606
-21
lines changed

src/labthings/schema.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# -*- coding: utf-8 -*-
22
from flask import url_for
33
from werkzeug.routing import BuildError
4-
from marshmallow import Schema, pre_load, pre_dump
4+
from marshmallow import Schema, pre_load, pre_dump, validate
55
from collections.abc import Mapping
66

77
from .names import TASK_ENDPOINT, EXTENSION_LIST_ENDPOINT
@@ -17,6 +17,7 @@
1717
"build_action_schema",
1818
"pre_load",
1919
"pre_dump",
20+
"validate",
2021
]
2122

2223

tests/old_api/__init__.py

Whitespace-only changes.

tests/old_api/conftest.py

Lines changed: 311 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
import pytest
2+
import os
3+
import json
4+
import jsonschema
5+
from flask import Flask
6+
from flask.views import MethodView
7+
from apispec import APISpec
8+
from apispec.ext.marshmallow import MarshmallowPlugin
9+
from labthings.server.labthing import LabThing
10+
from labthings.server.view import View
11+
12+
from werkzeug.test import EnvironBuilder
13+
from flask.testing import FlaskClient
14+
15+
16+
class Helpers:
17+
@staticmethod
18+
def validate_thing_description(thing_description, app_ctx, schemas_path):
19+
schema = json.load(open(os.path.join(schemas_path, "w3c_td_schema.json"), "r"))
20+
jsonschema.Draft7Validator.check_schema(schema)
21+
22+
with app_ctx.test_request_context():
23+
td_json = thing_description.to_dict()
24+
assert td_json
25+
26+
jsonschema.validate(instance=td_json, schema=schema)
27+
28+
29+
@pytest.fixture
30+
def helpers():
31+
return Helpers
32+
33+
34+
class FakeWebsocket:
35+
def __init__(self, message: str, recieve_once=True, close_after=None):
36+
self.message = message
37+
self.responses = []
38+
self.closed = False
39+
self.recieve_once = recieve_once
40+
41+
self.close_after = close_after or []
42+
43+
# I mean screw whoever is responsible for this having to be a thing...
44+
self.receive = self.recieve
45+
46+
def recieve(self):
47+
# Get message
48+
message_to_send = self.message
49+
# If only sending a message to the server once
50+
if self.recieve_once:
51+
# Clear our message
52+
self.message = None
53+
return message_to_send
54+
55+
@property
56+
def response(self):
57+
if len(self.responses) >= 1:
58+
return self.responses[-1]
59+
else:
60+
return None
61+
62+
def send(self, response):
63+
self.responses.append(response)
64+
# Close WS after getting the pre-defined unit test response
65+
if response in self.close_after:
66+
self.closed = True
67+
return response
68+
69+
70+
class JsonClient(FlaskClient):
71+
def open(self, *args, **kwargs):
72+
kwargs.setdefault(
73+
"headers",
74+
{"Content-Type": "application/json", "Accept": "application/json"},
75+
)
76+
kwargs.setdefault("content_type", "application/json")
77+
return super().open(*args, **kwargs)
78+
79+
80+
class SocketClient(FlaskClient):
81+
def __init__(self, app, response_wrapper, *args, **kwargs):
82+
super().__init__(app, response_wrapper, *args, **kwargs)
83+
self.app = app
84+
self.response_wrapper = response_wrapper
85+
self.socket = FakeWebsocket(message=None)
86+
self.environ_base = {
87+
"HTTP_UPGRADE": "websocket",
88+
"wsgi.websocket": self.socket,
89+
}
90+
91+
def connect(self, *args, message=None, **kwargs):
92+
kwargs.setdefault("environ_overrides", {})[
93+
"flask._preserve_context"
94+
] = self.preserve_context
95+
kwargs.setdefault("environ_base", self.environ_base)
96+
builder = EnvironBuilder(*args, **kwargs)
97+
98+
try:
99+
environ = builder.get_environ()
100+
finally:
101+
builder.close()
102+
103+
self.socket.message = message
104+
105+
with self.app.app_context():
106+
run_wsgi_app(self.app, environ)
107+
108+
# Once the connection has been closed, return responses
109+
return self.socket.responses
110+
111+
112+
def run_wsgi_app(app, environ, buffered=False):
113+
response = []
114+
buffer = []
115+
116+
def start_response(status, headers, exc_info=None):
117+
if exc_info:
118+
try:
119+
raise exc_info[1].with_traceback(exc_info[2])
120+
finally:
121+
exc_info = None
122+
response[:] = [status, headers]
123+
return buffer.append
124+
125+
# Return value from the wsgi_app call
126+
# In the case of our SocketMiddleware, will return []
127+
app_rv = app(environ, start_response)
128+
return app_rv
129+
130+
131+
@pytest.fixture
132+
def empty_view_cls():
133+
class EmptyViewClass(View):
134+
def get(self):
135+
pass
136+
137+
def post(self):
138+
pass
139+
140+
def put(self):
141+
pass
142+
143+
def delete(self):
144+
pass
145+
146+
return EmptyViewClass
147+
148+
149+
@pytest.fixture
150+
def flask_view_cls():
151+
class ViewClass(MethodView):
152+
def get(self):
153+
return "GET"
154+
155+
def post(self):
156+
return "POST"
157+
158+
def put(self):
159+
return "PUT"
160+
161+
def delete(self):
162+
return "DELETE"
163+
164+
return ViewClass
165+
166+
167+
@pytest.fixture
168+
def view_cls():
169+
class ViewClass(View):
170+
def get(self):
171+
return "GET"
172+
173+
def post(self):
174+
return "POST"
175+
176+
def put(self):
177+
return "PUT"
178+
179+
def delete(self):
180+
return "DELETE"
181+
182+
return ViewClass
183+
184+
185+
@pytest.fixture
186+
def spec():
187+
return APISpec(
188+
title="Python-LabThings PyTest",
189+
version="1.0.0",
190+
openapi_version="3.0.2",
191+
plugins=[MarshmallowPlugin()],
192+
)
193+
194+
195+
@pytest.fixture()
196+
def app(request):
197+
198+
app = Flask(__name__)
199+
app.config["TESTING"] = True
200+
201+
# pushes an application context manually
202+
ctx = app.app_context()
203+
ctx.push()
204+
205+
# bind the test life with the context through the
206+
request.addfinalizer(ctx.pop)
207+
return app
208+
209+
210+
@pytest.fixture
211+
def thing(app):
212+
thing = LabThing(app)
213+
with app.app_context():
214+
return thing
215+
216+
217+
@pytest.fixture()
218+
def thing_ctx(thing):
219+
with thing.app.app_context():
220+
yield thing.app
221+
222+
223+
@pytest.fixture()
224+
def debug_app(request):
225+
226+
app = Flask(__name__)
227+
app.config["TESTING"] = True
228+
app.debug = True
229+
230+
# pushes an application context manually
231+
ctx = app.app_context()
232+
ctx.push()
233+
234+
# bind the test life with the context through the
235+
request.addfinalizer(ctx.pop)
236+
return app
237+
238+
239+
@pytest.fixture()
240+
def app_ctx(app):
241+
with app.app_context():
242+
yield app
243+
244+
245+
@pytest.fixture()
246+
def app_ctx_debug(debug_app):
247+
with debug_app.app_context():
248+
yield debug_app
249+
250+
251+
@pytest.fixture
252+
def req_ctx(app):
253+
with app.test_request_context() as ctx:
254+
yield ctx
255+
256+
257+
@pytest.fixture
258+
def client(app):
259+
app.test_client_class = JsonClient
260+
return app.test_client()
261+
262+
263+
@pytest.fixture
264+
def debug_client(debug_app):
265+
debug_app.test_client_class = JsonClient
266+
return debug_app.test_client()
267+
268+
269+
@pytest.fixture
270+
def text_client(app):
271+
return app.test_client()
272+
273+
274+
@pytest.fixture
275+
def ws_client(app):
276+
app.test_client_class = SocketClient
277+
return app.test_client()
278+
279+
280+
@pytest.fixture
281+
def thing_client(thing):
282+
thing.app.test_client_class = JsonClient
283+
return thing.app.test_client()
284+
285+
286+
@pytest.fixture
287+
def static_path(app):
288+
return os.path.join(os.path.dirname(__file__), "static")
289+
290+
291+
@pytest.fixture
292+
def schemas_path(app):
293+
return os.path.join(os.path.dirname(__file__), "schemas")
294+
295+
296+
@pytest.fixture
297+
def extensions_path(app):
298+
return os.path.join(os.path.dirname(__file__), "extensions")
299+
300+
301+
@pytest.fixture
302+
def fake_websocket():
303+
"""
304+
Return a fake websocket client
305+
that sends a given message, waits for a response, then closes
306+
"""
307+
308+
def _foo(*args, **kwargs):
309+
return FakeWebsocket(*args, **kwargs)
310+
311+
return _foo

tests/old_api/extensions/extension.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from labthings.server.extensions import BaseExtension
2+
3+
test_extension = BaseExtension("org.labthings.tests.extension")
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
raise Exception
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from labthings.server.extensions import BaseExtension
2+
3+
test_extension = BaseExtension("org.labthings.tests.extension")
4+
test_extension_excluded = BaseExtension("org.labthings.tests.extension_excluded")
5+
6+
__extensions__ = ["test_extension"]
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from labthings.server.extensions import BaseExtension
2+
3+
test_extension = BaseExtension("org.labthings.tests.extension_package")

0 commit comments

Comments
 (0)