Add server tests
This commit is contained in:
parent
61c9d53cf3
commit
74e44b1e8c
6 changed files with 86 additions and 10 deletions
47
poetry.lock
generated
47
poetry.lock
generated
|
@ -242,6 +242,39 @@ files = [
|
|||
[package.extras]
|
||||
tests = ["freezegun", "pytest", "pytest-cov"]
|
||||
|
||||
[[package]]
|
||||
name = "hypothesis"
|
||||
version = "6.68.2"
|
||||
description = "A library for property-based testing"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "hypothesis-6.68.2-py3-none-any.whl", hash = "sha256:2a41cc766cde52705895e54547374af89c617e8ec7bc4186cb7f03884a667d4e"},
|
||||
{file = "hypothesis-6.68.2.tar.gz", hash = "sha256:a7eb2b0c9a18560d8197fe35047ceb58e7e8ab7623a3e5a82613f6a2cd71cffa"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
attrs = ">=19.2.0"
|
||||
exceptiongroup = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
|
||||
sortedcontainers = ">=2.1.0,<3.0.0"
|
||||
|
||||
[package.extras]
|
||||
all = ["backports.zoneinfo (>=0.2.1)", "black (>=19.10b0)", "click (>=7.0)", "django (>=3.2)", "dpcontracts (>=0.4)", "importlib-metadata (>=3.6)", "lark (>=0.10.1)", "libcst (>=0.3.16)", "numpy (>=1.9.0)", "pandas (>=1.0)", "pytest (>=4.6)", "python-dateutil (>=1.4)", "pytz (>=2014.1)", "redis (>=3.0.0)", "rich (>=9.0.0)", "tzdata (>=2022.7)"]
|
||||
cli = ["black (>=19.10b0)", "click (>=7.0)", "rich (>=9.0.0)"]
|
||||
codemods = ["libcst (>=0.3.16)"]
|
||||
dateutil = ["python-dateutil (>=1.4)"]
|
||||
django = ["django (>=3.2)"]
|
||||
dpcontracts = ["dpcontracts (>=0.4)"]
|
||||
ghostwriter = ["black (>=19.10b0)"]
|
||||
lark = ["lark (>=0.10.1)"]
|
||||
numpy = ["numpy (>=1.9.0)"]
|
||||
pandas = ["pandas (>=1.0)"]
|
||||
pytest = ["pytest (>=4.6)"]
|
||||
pytz = ["pytz (>=2014.1)"]
|
||||
redis = ["redis (>=3.0.0)"]
|
||||
zoneinfo = ["backports.zoneinfo (>=0.2.1)", "tzdata (>=2022.7)"]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "3.4"
|
||||
|
@ -916,6 +949,18 @@ files = [
|
|||
{file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sortedcontainers"
|
||||
version = "2.4.0"
|
||||
description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"},
|
||||
{file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tomli"
|
||||
version = "2.0.1"
|
||||
|
@ -1045,4 +1090,4 @@ watchdog = ["watchdog"]
|
|||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.9"
|
||||
content-hash = "bacbfb300aa1f8e518650103e8b1a4cdf6696d44aa755a7a0f0f326f53554adc"
|
||||
content-hash = "d0c041b102dde383652dafd83634e799ea85c38df4053765335a36a97ee18c80"
|
||||
|
|
|
@ -27,6 +27,16 @@ pytest-mypy = "*"
|
|||
black = "*"
|
||||
mypy = "*"
|
||||
types-pyyaml = "^6.0"
|
||||
hypothesis = "^6.68.2"
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
addopts = "--mypy"
|
||||
filterwarnings = """
|
||||
ignore::DeprecationWarning:openapi_core.*:
|
||||
ignore::DeprecationWarning:openapi_schema_validator.*:
|
||||
ignore::DeprecationWarning:openapi_spec_validator.*:
|
||||
ignore::DeprecationWarning:jsonschema.*:
|
||||
"""
|
||||
|
||||
[tool.mypy]
|
||||
plugins = "returns.contrib.mypy.returns_plugin"
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
import importlib.metadata
|
||||
import importlib.resources
|
||||
import os
|
||||
from unittest.mock import patch
|
||||
|
||||
import tornado.template
|
||||
import tornado_openapi3.testing
|
||||
import yaml
|
||||
|
||||
import tutor.database
|
||||
import tutor.server
|
||||
|
||||
template_path = importlib.resources.path("tutor", "templates")
|
||||
template_loader = tornado.template.Loader(template_path)
|
||||
template_loader = tornado.template.Loader(str(template_path))
|
||||
openapi_spec_dict = yaml.safe_load(
|
||||
template_loader.load("openapi.yaml").generate(
|
||||
version=importlib.metadata.version("tutor")
|
||||
|
@ -23,8 +26,17 @@ class ServerTestCase(tornado_openapi3.testing.AsyncOpenAPITestCase):
|
|||
global openapi_spec_dict
|
||||
return openapi_spec_dict
|
||||
|
||||
@property
|
||||
def spec(self):
|
||||
global openapi_spec
|
||||
if not openapi_spec:
|
||||
openapi_spec = super().spec
|
||||
return openapi_spec
|
||||
|
||||
def get_app(self):
|
||||
return tutor.server.Application()
|
||||
return tutor.server.Application(
|
||||
database=os.environ.get("TUTOR_DATABASE"),
|
||||
)
|
||||
|
||||
|
||||
class DocumentationTestCase(ServerTestCase):
|
||||
|
@ -33,3 +45,8 @@ class DocumentationTestCase(ServerTestCase):
|
|||
|
||||
def test_openapi_yaml(self):
|
||||
self.fetch("/api/openapi.yaml")
|
||||
|
||||
|
||||
class APITestCase(ServerTestCase):
|
||||
def test_collection_stats(self):
|
||||
self.fetch("/api/collection")
|
||||
|
|
|
@ -41,6 +41,8 @@ def update_args(url: str, **qargs) -> str:
|
|||
|
||||
class JSONEncoder(json.JSONEncoder):
|
||||
def default(self, obj):
|
||||
if isinstance(obj, decimal.Decimal):
|
||||
return float(obj)
|
||||
if isinstance(obj, tutor.models.Card):
|
||||
return self._card(obj)
|
||||
if isinstance(obj, tutor.models.CardCopy):
|
||||
|
@ -201,9 +203,11 @@ class CollectionHandler(RequestHandler):
|
|||
async def get(self) -> None:
|
||||
async with self.pool.connection() as conn:
|
||||
async with conn.cursor() as cursor:
|
||||
self.set_header("Content-Type", "application/json")
|
||||
self.set_header("Access-Control-Allow-Origin", "*")
|
||||
self.write(
|
||||
json.dumps(
|
||||
await tutor.database.collection_stats(cursor), default=str
|
||||
await tutor.database.collection_stats(cursor), cls=JSONEncoder
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -252,7 +256,7 @@ class TemplateHandler(RequestHandler):
|
|||
self,
|
||||
path: str,
|
||||
content_type: str = "application/octet-stream",
|
||||
vars: dict = None,
|
||||
vars: typing.Optional[dict] = None,
|
||||
):
|
||||
self.path = path
|
||||
self.content_type = content_type
|
||||
|
|
|
@ -33,7 +33,7 @@ paths:
|
|||
schema:
|
||||
type: string
|
||||
|
||||
/search:
|
||||
/api/search:
|
||||
get:
|
||||
summary: Search the card database
|
||||
tags:
|
||||
|
@ -141,7 +141,7 @@ paths:
|
|||
responses:
|
||||
'200':
|
||||
description: Search results
|
||||
/collection:
|
||||
/api/collection:
|
||||
get:
|
||||
summary: Collection statistics
|
||||
tags:
|
||||
|
|
|
@ -32,7 +32,7 @@ import Url.Parser.Query
|
|||
type alias Statistics =
|
||||
{ cards : Int
|
||||
, sets : Int
|
||||
, value : String
|
||||
, value : Float
|
||||
}
|
||||
|
||||
|
||||
|
@ -41,7 +41,7 @@ decodeStatistics =
|
|||
Json.Decode.succeed Statistics
|
||||
|> JDP.required "cards" Json.Decode.int
|
||||
|> JDP.required "sets" Json.Decode.int
|
||||
|> JDP.required "value" Json.Decode.string
|
||||
|> JDP.required "value" Json.Decode.float
|
||||
|
||||
|
||||
type alias Criteria =
|
||||
|
@ -573,7 +573,7 @@ view model =
|
|||
, " cards in collection spanning "
|
||||
, String.fromInt statistics.sets
|
||||
, " sets (Estimated value: $"
|
||||
, statistics.value
|
||||
, String.fromFloat statistics.value
|
||||
, ")"
|
||||
]
|
||||
|
||||
|
|
Loading…
Reference in a new issue