✅ Bumped coverage
This commit is contained in:
-102
@@ -1,102 +0,0 @@
|
|||||||
# A generic, single database configuration.
|
|
||||||
|
|
||||||
[alembic]
|
|
||||||
# path to migration scripts
|
|
||||||
script_location = alembic
|
|
||||||
|
|
||||||
# template used to generate migration files
|
|
||||||
# file_template = %%(rev)s_%%(slug)s
|
|
||||||
|
|
||||||
# sys.path path, will be prepended to sys.path if present.
|
|
||||||
# defaults to the current working directory.
|
|
||||||
prepend_sys_path = .
|
|
||||||
|
|
||||||
# timezone to use when rendering the date within the migration file
|
|
||||||
# as well as the filename.
|
|
||||||
# If specified, requires the python-dateutil library that can be
|
|
||||||
# installed by adding `alembic[tz]` to the pip requirements
|
|
||||||
# string value is passed to dateutil.tz.gettz()
|
|
||||||
# leave blank for localtime
|
|
||||||
# timezone =
|
|
||||||
|
|
||||||
# max length of characters to apply to the
|
|
||||||
# "slug" field
|
|
||||||
# truncate_slug_length = 40
|
|
||||||
|
|
||||||
# set to 'true' to run the environment during
|
|
||||||
# the 'revision' command, regardless of autogenerate
|
|
||||||
# revision_environment = false
|
|
||||||
|
|
||||||
# set to 'true' to allow .pyc and .pyo files without
|
|
||||||
# a source .py file to be detected as revisions in the
|
|
||||||
# versions/ directory
|
|
||||||
# sourceless = false
|
|
||||||
|
|
||||||
# version location specification; This defaults
|
|
||||||
# to alembic/versions. When using multiple version
|
|
||||||
# directories, initial revisions must be specified with --version-path.
|
|
||||||
# The path separator used here should be the separator specified by "version_path_separator" below.
|
|
||||||
# version_locations = %(here)s/bar:%(here)s/bat:alembic/versions
|
|
||||||
|
|
||||||
# version path separator; As mentioned above, this is the character used to split
|
|
||||||
# version_locations. The default within new alembic.ini files is "os", which uses os.pathsep.
|
|
||||||
# If this key is omitted entirely, it falls back to the legacy behavior of splitting on spaces and/or commas.
|
|
||||||
# Valid values for version_path_separator are:
|
|
||||||
#
|
|
||||||
# version_path_separator = :
|
|
||||||
# version_path_separator = ;
|
|
||||||
# version_path_separator = space
|
|
||||||
version_path_separator = os # Use os.pathsep. Default configuration used for new projects.
|
|
||||||
|
|
||||||
# the output encoding used when revision files
|
|
||||||
# are written from script.py.mako
|
|
||||||
# output_encoding = utf-8
|
|
||||||
|
|
||||||
sqlalchemy.url = asdas
|
|
||||||
|
|
||||||
|
|
||||||
[post_write_hooks]
|
|
||||||
# post_write_hooks defines scripts or Python functions that are run
|
|
||||||
# on newly generated revision scripts. See the documentation for further
|
|
||||||
# detail and examples
|
|
||||||
|
|
||||||
# format using "black" - use the console_scripts runner, against the "black" entrypoint
|
|
||||||
# hooks = black
|
|
||||||
# black.type = console_scripts
|
|
||||||
# black.entrypoint = black
|
|
||||||
# black.options = -l 79 REVISION_SCRIPT_FILENAME
|
|
||||||
|
|
||||||
# Logging configuration
|
|
||||||
[loggers]
|
|
||||||
keys = root,sqlalchemy,alembic
|
|
||||||
|
|
||||||
[handlers]
|
|
||||||
keys = console
|
|
||||||
|
|
||||||
[formatters]
|
|
||||||
keys = generic
|
|
||||||
|
|
||||||
[logger_root]
|
|
||||||
level = WARN
|
|
||||||
handlers = console
|
|
||||||
qualname =
|
|
||||||
|
|
||||||
[logger_sqlalchemy]
|
|
||||||
level = WARN
|
|
||||||
handlers =
|
|
||||||
qualname = sqlalchemy.engine
|
|
||||||
|
|
||||||
[logger_alembic]
|
|
||||||
level = INFO
|
|
||||||
handlers =
|
|
||||||
qualname = alembic
|
|
||||||
|
|
||||||
[handler_console]
|
|
||||||
class = StreamHandler
|
|
||||||
args = (sys.stderr,)
|
|
||||||
level = NOTSET
|
|
||||||
formatter = generic
|
|
||||||
|
|
||||||
[formatter_generic]
|
|
||||||
format = %(levelname)-5.5s [%(name)s] %(message)s
|
|
||||||
datefmt = %H:%M:%S
|
|
||||||
@@ -1,16 +1,35 @@
|
|||||||
import pytest
|
|
||||||
from typing import Generator
|
from typing import Generator
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
from classquiz import app
|
|
||||||
|
# from classquiz.socket_server import sio
|
||||||
|
from classquiz import app as fastapi_app
|
||||||
|
|
||||||
|
# from typing import List, Optional
|
||||||
|
|
||||||
|
# stdlib imports
|
||||||
|
# import asyncio
|
||||||
|
|
||||||
|
# 3rd party imports
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
# import socketio
|
||||||
|
# import uvicorn
|
||||||
|
|
||||||
|
# FastAPI imports
|
||||||
|
# from fastapi import FastAPI
|
||||||
|
|
||||||
|
PORT = 8000
|
||||||
|
|
||||||
|
|
||||||
class ValueStorage:
|
class ValueStorage:
|
||||||
quiz_id = None
|
quiz_id = None
|
||||||
imported_quizzes = [None]
|
imported_quizzes = []
|
||||||
|
game_pin = None
|
||||||
|
game_id = None
|
||||||
|
|
||||||
|
|
||||||
example_quiz = {
|
example_quiz = {
|
||||||
"public": False,
|
"public": True,
|
||||||
"title": "Some test question",
|
"title": "Some test question",
|
||||||
"description": "A description",
|
"description": "A description",
|
||||||
"questions": [
|
"questions": [
|
||||||
@@ -37,5 +56,52 @@ test_user_password = "test"
|
|||||||
|
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def test_client() -> Generator:
|
def test_client() -> Generator:
|
||||||
with TestClient(app) as testclient:
|
with TestClient(fastapi_app) as testclient:
|
||||||
yield testclient
|
yield testclient
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# sio.eio.start_service_task = False
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# class UvicornTestServer(uvicorn.Server):
|
||||||
|
# """Uvicorn test server
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# @pytest.fixture
|
||||||
|
# async def start_stop_server():
|
||||||
|
# server = UvicornTestServer()
|
||||||
|
# await server.up()
|
||||||
|
# yield
|
||||||
|
# await server.down()
|
||||||
|
# """
|
||||||
|
#
|
||||||
|
# def __init__(self, app: FastAPI = fastapi_app, host: str = '127.0.0.1', port: int = PORT):
|
||||||
|
# """Create a Uvicorn test server
|
||||||
|
#
|
||||||
|
# Args:
|
||||||
|
# app (FastAPI, optional): the FastAPI app. Defaults to main.app.
|
||||||
|
# host (str, optional): the host ip. Defaults to '127.0.0.1'.
|
||||||
|
# port (int, optional): the port. Defaults to PORT.
|
||||||
|
# """
|
||||||
|
# self._startup_done = asyncio.Event()
|
||||||
|
# super().__init__(config=uvicorn.Config(app, host=host, port=port))
|
||||||
|
#
|
||||||
|
# async def startup(self, sockets: Optional[List] = None) -> None:
|
||||||
|
# """Override uvicorn startup"""
|
||||||
|
# await super().startup(sockets=sockets)
|
||||||
|
# self.config.setup_event_loop()
|
||||||
|
# self._startup_done.set()
|
||||||
|
#
|
||||||
|
# async def up(self) -> None:
|
||||||
|
# """Start up server asynchronously"""
|
||||||
|
# self._serve_task = asyncio.create_task(self.serve())
|
||||||
|
# await self._startup_done.wait()
|
||||||
|
#
|
||||||
|
# async def down(self) -> None:
|
||||||
|
# """Shut down server asynchronously"""
|
||||||
|
# self.should_exit = True
|
||||||
|
# await self._serve_task
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|||||||
+111
-14
@@ -8,6 +8,17 @@ from classquiz.tests import test_user_email, test_user_password
|
|||||||
from classquiz.tests import test_client, example_quiz, ValueStorage
|
from classquiz.tests import test_client, example_quiz, ValueStorage
|
||||||
|
|
||||||
|
|
||||||
|
# @pytest.fixture
|
||||||
|
# async def startup_and_shutdown_server():
|
||||||
|
# """Start server as test fixture and tear down after test"""
|
||||||
|
# print("starting up")
|
||||||
|
# server = UvicornTestServer()
|
||||||
|
# await server.up()
|
||||||
|
# print("Server up")
|
||||||
|
# yield
|
||||||
|
# await server.down()
|
||||||
|
|
||||||
|
|
||||||
class TestUsers:
|
class TestUsers:
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_create_test_user(self, test_client):
|
async def test_create_test_user(self, test_client):
|
||||||
@@ -330,21 +341,14 @@ class TestQuiz:
|
|||||||
"/api/v1/quiz/update/saddsaasddsadsa", json=example_quiz, cookies={"access_token": token}
|
"/api/v1/quiz/update/saddsaasddsadsa", json=example_quiz, cookies={"access_token": token}
|
||||||
)
|
)
|
||||||
assert resp.status_code == 400
|
assert resp.status_code == 400
|
||||||
|
example_quiz["public"] = False
|
||||||
@pytest.mark.asyncio
|
test_client.put(
|
||||||
async def test_get_public_quiz(self, test_client):
|
f"/api/v1/quiz/update/{ValueStorage.quiz_id}", json=example_quiz, cookies={"access_token": token}
|
||||||
resp = test_client.post(
|
|
||||||
"/api/v1/users/token/cookie", data={"username": test_user_email, "password": test_user_password}
|
|
||||||
)
|
)
|
||||||
token = resp.cookies["access_token"]
|
example_quiz["public"] = True
|
||||||
resp = test_client.get(f"/api/v1/quiz/get/{ValueStorage.quiz_id}", cookies={"access_token": token})
|
test_client.put(
|
||||||
assert resp.status_code == 200
|
f"/api/v1/quiz/update/{ValueStorage.quiz_id}", json=example_quiz, cookies={"access_token": token}
|
||||||
resp = test_client.get(
|
|
||||||
"/api/v1/quiz/get/public/f183e091-a863-44ec-a1b7-c70eb92e3f6a", cookies={"access_token": token}
|
|
||||||
)
|
)
|
||||||
assert resp.status_code == 404
|
|
||||||
resp = test_client.get("/api/v1/quiz/get/public/dadasdas92e3f6a", cookies={"access_token": token})
|
|
||||||
assert resp.status_code == 400
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_import_quiz(self, test_client):
|
async def test_import_quiz(self, test_client):
|
||||||
@@ -360,8 +364,101 @@ class TestQuiz:
|
|||||||
resp = test_client.post("/api/v1/quiz/import/1f95eb0bdassdadasdas", cookies={"access_token": token})
|
resp = test_client.post("/api/v1/quiz/import/1f95eb0bdassdadasdas", cookies={"access_token": token})
|
||||||
assert resp.text == '"quiz not found"'
|
assert resp.text == '"quiz not found"'
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_get_public_quiz(self, test_client):
|
||||||
|
resp = test_client.post(
|
||||||
|
"/api/v1/users/token/cookie", data={"username": test_user_email, "password": test_user_password}
|
||||||
|
)
|
||||||
|
token = resp.cookies["access_token"]
|
||||||
|
resp = test_client.get(f"/api/v1/quiz/get/public/{ValueStorage.imported_quizzes[0]}")
|
||||||
|
assert resp.status_code == 200
|
||||||
|
resp = test_client.get(
|
||||||
|
"/api/v1/quiz/get/public/f183e091-a863-44ec-a1b7-c70eb92e3f6a", cookies={"access_token": token}
|
||||||
|
)
|
||||||
|
assert resp.status_code == 404
|
||||||
|
resp = test_client.get("/api/v1/quiz/get/public/dadasdas92e3f6a", cookies={"access_token": token})
|
||||||
|
assert resp.status_code == 400
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_search_get(self, test_client):
|
||||||
|
resp = test_client.get("/api/v1/search/?q=*")
|
||||||
|
assert resp.status_code == 200
|
||||||
|
assert len(resp.json()["hits"]) > 0
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_search_post(self, test_client):
|
||||||
|
resp = test_client.post("/api/v1/search/", json={"q": "*"})
|
||||||
|
assert resp.status_code == 200
|
||||||
|
assert len(resp.json()["hits"]) > 0
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_image_cdn(self, test_client):
|
||||||
|
resp = test_client.get(f"/api/v1/quiz/get/public/{ValueStorage.imported_quizzes[0]}")
|
||||||
|
assert resp.status_code == 200
|
||||||
|
quiz = resp.json()
|
||||||
|
image_url = quiz["questions"][0]["image"]
|
||||||
|
resp = test_client.get(image_url)
|
||||||
|
assert resp.status_code == 200
|
||||||
|
resp = test_client.get(f"{image_url}sadgvsadgvhsad")
|
||||||
|
assert resp.status_code == 400
|
||||||
|
|
||||||
|
|
||||||
|
class TestPlayQuiz:
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_start_quiz(self, test_client):
|
||||||
|
resp = test_client.post(
|
||||||
|
"/api/v1/users/token/cookie", data={"username": test_user_email, "password": test_user_password}
|
||||||
|
)
|
||||||
|
token = resp.cookies["access_token"]
|
||||||
|
resp = test_client.post(
|
||||||
|
"/api/v1/quiz/start/fb5adc91-629e-416e-8b98-ae400e36417c", cookies={"access_token": token}
|
||||||
|
)
|
||||||
|
assert resp.status_code == 404
|
||||||
|
resp = test_client.post(
|
||||||
|
"/api/v1/quiz/start/fb5adc91-629e-416e-8b98-ae400sdadsasadsadasddsae36417c", cookies={"access_token": token}
|
||||||
|
)
|
||||||
|
assert resp.status_code == 400
|
||||||
|
resp = test_client.post(f"/api/v1/quiz/start/{ValueStorage.quiz_id}", cookies={"access_token": token})
|
||||||
|
ValueStorage.game_pin = resp.json()["game_pin"]
|
||||||
|
ValueStorage.game_id = resp.json()["game_id"]
|
||||||
|
|
||||||
|
# @pytest.mark.asyncio
|
||||||
|
# async def test_actual_play(self, startup_and_shutdown_server):
|
||||||
|
# admin_client = socketio.AsyncClient()
|
||||||
|
# player1_client = socketio.AsyncClient()
|
||||||
|
# player2_client = socketio.AsyncClient()
|
||||||
|
# future = asyncio.get_running_loop().create_future()
|
||||||
|
# time.sleep(1)
|
||||||
|
# await admin_client.connect(f'http://localhost:{PORT}', socketio_path='/socket.io/')
|
||||||
|
# await player1_client.connect(f'http://localhost:{PORT}', socketio_path="/socket.io")
|
||||||
|
# await player2_client.connect(f'http://localhost:{PORT}', socketio_path="/socket.io")
|
||||||
|
#
|
||||||
|
# await admin_client.disconnect()
|
||||||
|
# await player1_client.disconnect()
|
||||||
|
# await player2_client.disconnect()
|
||||||
|
|
||||||
|
|
||||||
|
class TestDeleteStuff:
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_delete_quiz(self, test_client):
|
||||||
|
resp = test_client.post(
|
||||||
|
"/api/v1/users/token/cookie", data={"username": test_user_email, "password": test_user_password}
|
||||||
|
)
|
||||||
|
token = resp.cookies["access_token"]
|
||||||
|
resp = test_client.delete(
|
||||||
|
f"/api/v1/quiz/delete/{ValueStorage.imported_quizzes[0]}", cookies={"access_token": token}
|
||||||
|
)
|
||||||
|
assert resp.status_code == 200
|
||||||
|
resp = test_client.delete(
|
||||||
|
"/api/v1/quiz/delete/be582c77-da03-4271-929c-5d582056eb78", cookies={"access_token": token}
|
||||||
|
)
|
||||||
|
assert resp.status_code == 404
|
||||||
|
|
||||||
|
resp = test_client.delete(
|
||||||
|
"/api/v1/quiz/delete/be582c77-da03-sdaasdadsasddas4271-929c-5d582056eb78", cookies={"access_token": token}
|
||||||
|
)
|
||||||
|
assert resp.status_code == 400
|
||||||
|
|
||||||
class TestDeleteUser:
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_delete_user(self, test_client):
|
async def test_delete_user(self, test_client):
|
||||||
resp = test_client.post(
|
resp = test_client.post(
|
||||||
|
|||||||
Reference in New Issue
Block a user