Some bugfix
This commit is contained in:
@@ -24,7 +24,7 @@ jobs:
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.9
|
||||
python-version: 3.12
|
||||
architecture: x64
|
||||
|
||||
- name: Install dependencies
|
||||
|
||||
+11
-3
@@ -9,6 +9,8 @@ from dotenv import load_dotenv
|
||||
from fastapi import FastAPI, Depends, Response, Header, HTTPException, status
|
||||
from guard import SecurityMiddleware, SecurityConfig
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from schemas.api_schemas import BaseResponse, AddUserBody, AddCardBody, SelectChoice, ReactionCard, AddCommentBody
|
||||
from schemas.base_schemas import Card
|
||||
from mongo_worker import MongoWorker
|
||||
@@ -42,7 +44,14 @@ config = SecurityConfig(
|
||||
|
||||
app.add_middleware(SecurityMiddleware, config=config)
|
||||
mongo_worker = MongoWorker()
|
||||
rabbit_worker = RabbitWorker()
|
||||
_rabbit_worker: Optional[RabbitWorker] = None
|
||||
|
||||
|
||||
def get_rabbit_worker() -> RabbitWorker:
|
||||
global _rabbit_worker
|
||||
if _rabbit_worker is None:
|
||||
_rabbit_worker = RabbitWorker()
|
||||
return _rabbit_worker
|
||||
|
||||
MODERATION_SECRET = os.getenv("MODERATION_SECRET", "change-me-in-production")
|
||||
|
||||
@@ -50,7 +59,6 @@ MODERATION_SECRET = os.getenv("MODERATION_SECRET", "change-me-in-production")
|
||||
async def verify_moderation_secret(
|
||||
x_moderation_secret: str = Header(..., alias="X-Moderation-Secret"),
|
||||
) -> str:
|
||||
"""Проверяет секретный ключ модерации в заголовке запроса."""
|
||||
if not secrets.compare_digest(x_moderation_secret, MODERATION_SECRET):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
@@ -146,7 +154,7 @@ async def add_card(
|
||||
|
||||
# Отправляем карточку в RabbitMQ на ручную модерацию админом
|
||||
try:
|
||||
await rabbit_worker.send_to_moderation(card)
|
||||
await get_rabbit_worker().send_to_moderation(card)
|
||||
except Exception as exc:
|
||||
logger.error("Failed to send card %s to moderation queue: %s", card.card_id, exc)
|
||||
|
||||
|
||||
+14
-14
@@ -14,7 +14,7 @@ NON_EXIST_CARD_ID = 1000
|
||||
|
||||
# ---------- /add_card ----------
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.asyncio(loop_scope="session")
|
||||
async def test_add_card_valid():
|
||||
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
|
||||
payload = {
|
||||
@@ -32,7 +32,7 @@ async def test_add_card_valid():
|
||||
assert card.choice_B == payload["choice_B"]
|
||||
assert card.author_id == payload["author_id"]
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.asyncio(loop_scope="session")
|
||||
async def test_add_card_missing_field():
|
||||
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
|
||||
payload = {
|
||||
@@ -44,7 +44,7 @@ async def test_add_card_missing_field():
|
||||
print(f"\nINPUT: endpoint=/add_card | payload (missing field)={payload}\nOUTPUT: status={response.status_code} | json={response.json()}")
|
||||
assert response.status_code == 422
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.asyncio(loop_scope="session")
|
||||
async def test_add_card_wrong_type():
|
||||
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
|
||||
payload = {
|
||||
@@ -56,7 +56,7 @@ async def test_add_card_wrong_type():
|
||||
print(f"\nINPUT: endpoint=/add_card | payload (wrong type)={payload}\nOUTPUT: status={response.status_code} | json={response.json()}")
|
||||
assert response.status_code == 422
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.asyncio(loop_scope="session")
|
||||
async def test_add_card_empty_strings():
|
||||
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
|
||||
payload = {
|
||||
@@ -68,7 +68,7 @@ async def test_add_card_empty_strings():
|
||||
print(f"\nINPUT: endpoint=/add_card | payload (empty strings)={payload}\nOUTPUT: status={response.status_code} | json={response.json()}")
|
||||
assert response.status_code == 400
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.asyncio(loop_scope="session")
|
||||
async def test_add_card_long_strings():
|
||||
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
|
||||
long_str = "A" * 5000 # long string
|
||||
@@ -81,7 +81,7 @@ async def test_add_card_long_strings():
|
||||
print(f"\nINPUT: endpoint=/add_card | payload with long strings (length={len(long_str)})\nOUTPUT: status={response.status_code} | json={response.json()}")
|
||||
assert response.status_code == 400
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.asyncio(loop_scope="session")
|
||||
async def test_add_card_negative_author_id():
|
||||
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
|
||||
payload = {
|
||||
@@ -93,7 +93,7 @@ async def test_add_card_negative_author_id():
|
||||
print(f"\nINPUT: endpoint=/add_card | payload (negative author_id)={payload}\nOUTPUT: status={response.status_code} | json={response.json()}")
|
||||
assert response.status_code == 422
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.asyncio(loop_scope="session")
|
||||
async def test_add_card_malformed_json():
|
||||
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
|
||||
malformed_json = '{"choice_A": "Option A", "choice_B": "Option B", "author_id": 123' # broken json
|
||||
@@ -105,7 +105,7 @@ async def test_add_card_malformed_json():
|
||||
print(f"\nINPUT: endpoint=/add_card | payload (malformed JSON)={malformed_json}\nOUTPUT: status={response.status_code} | json={response.json() if response.content else 'No JSON'}")
|
||||
assert response.status_code == 422
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.asyncio(loop_scope="session")
|
||||
async def test_async_card_creation():
|
||||
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
|
||||
tasks = []
|
||||
@@ -136,7 +136,7 @@ async def test_async_card_creation():
|
||||
|
||||
# ---------- /get_card ----------
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.asyncio(loop_scope="session")
|
||||
async def test_get_card_valid():
|
||||
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
|
||||
payload = {
|
||||
@@ -157,30 +157,30 @@ async def test_get_card_valid():
|
||||
card_from_get = Card.model_validate(base_resp.result)
|
||||
assert card_from_get.card_id == card_id
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.asyncio(loop_scope="session")
|
||||
async def test_get_card_nonexistent():
|
||||
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
|
||||
response = await client.get("/get_card", params={"card_id": NON_EXIST_CARD_ID})
|
||||
print(f"\nINPUT: endpoint=/get_card | params={{'card_id': {NON_EXIST_CARD_ID}}}\nOUTPUT: status={response.status_code} | json={response.json()}")
|
||||
assert response.status_code == 404
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.asyncio(loop_scope="session")
|
||||
async def test_get_card_missing_param():
|
||||
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
|
||||
response = await client.get("/get_card")
|
||||
print(f"\nINPUT: endpoint=/get_card (missing card_id param)\nOUTPUT: status={response.status_code} | json={response.json() if response.content else 'No content'}")
|
||||
assert response.status_code == 422
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.asyncio(loop_scope="session")
|
||||
async def test_get_card_wrong_type():
|
||||
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
|
||||
response = await client.get("/get_card", params={"card_id": "abc"})
|
||||
print(f"\nINPUT: endpoint=/get_card | params={{'card_id': 'abc'}}\nOUTPUT: status={response.status_code} | json={response.json()}")
|
||||
assert response.status_code == 422
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.asyncio(loop_scope="session")
|
||||
async def test_get_card_negative():
|
||||
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
|
||||
response = await client.get("/get_card", params={"card_id": -10})
|
||||
print(f"\nINPUT: endpoint=/get_card | params={{'card_id': -10}}\nOUTPUT: status={response.status_code} | json={response.json()}")
|
||||
assert response.status_code == 422
|
||||
assert response.status_code == 404
|
||||
@@ -16,7 +16,7 @@ NON_EXIST_USER = random.randint(100000000, 1000000000)
|
||||
|
||||
# TEST ADD USERS UTILS #
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.asyncio(loop_scope="session")
|
||||
async def test_add_user_non_full_data():
|
||||
async with AsyncClient(transport=ASGITransport(app=app),
|
||||
base_url='http://test') as client:
|
||||
@@ -30,7 +30,7 @@ async def test_add_user_non_full_data():
|
||||
|
||||
assert raw_response.status_code == 422
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.asyncio(loop_scope="session")
|
||||
async def test_add_user_negative_int_id():
|
||||
async with AsyncClient(transport=ASGITransport(app=app),
|
||||
base_url='http://test') as client:
|
||||
@@ -47,7 +47,7 @@ async def test_add_user_negative_int_id():
|
||||
|
||||
assert raw_response.status_code == 422
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.asyncio(loop_scope="session")
|
||||
async def test_add_new_user():
|
||||
async with AsyncClient(transport=ASGITransport(app=app),
|
||||
base_url='http://test') as client:
|
||||
@@ -67,7 +67,7 @@ async def test_add_new_user():
|
||||
assert response.error == False
|
||||
assert User.model_validate(response.result)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.asyncio(loop_scope="session")
|
||||
async def test_add_already_exist_user():
|
||||
async with AsyncClient(transport=ASGITransport(app=app),
|
||||
base_url='http://test') as client:
|
||||
@@ -92,7 +92,7 @@ async def test_add_already_exist_user():
|
||||
|
||||
# TEST CHECK USERS UTILS #
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.asyncio(loop_scope="session")
|
||||
async def test_check_non_exist_user():
|
||||
async with AsyncClient(transport=ASGITransport(app=app),
|
||||
base_url='http://test') as client:
|
||||
@@ -106,7 +106,7 @@ async def test_check_non_exist_user():
|
||||
assert response.error == False
|
||||
assert response.result == False
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.asyncio(loop_scope="session")
|
||||
async def test_check_exist_user():
|
||||
async with AsyncClient(transport=ASGITransport(app=app),
|
||||
base_url='http://test') as client:
|
||||
@@ -125,7 +125,7 @@ async def test_check_exist_user():
|
||||
|
||||
# TEST GET USERS UTILS #
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.asyncio(loop_scope="session")
|
||||
async def test_get_non_exist_user():
|
||||
async with AsyncClient(transport=ASGITransport(app=app),
|
||||
base_url='http://test') as client:
|
||||
@@ -139,7 +139,7 @@ async def test_get_non_exist_user():
|
||||
assert response.error == True
|
||||
assert response.result == "User doesn't exist"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.asyncio(loop_scope="session")
|
||||
async def test_get_exist_user():
|
||||
async with AsyncClient(transport=ASGITransport(app=app),
|
||||
base_url='http://test') as client:
|
||||
|
||||
@@ -14,7 +14,7 @@ ACTIVE_CARDS_LESS_THAN_TEN = False
|
||||
|
||||
# ------------- /add_user ---------------
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.asyncio(loop_scope="session")
|
||||
async def test_add_new_user():
|
||||
async with AsyncClient(transport=ASGITransport(app=app),
|
||||
base_url='http://test') as client:
|
||||
@@ -36,7 +36,7 @@ async def test_add_new_user():
|
||||
|
||||
# ---------- /get_random_cards ----------
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.asyncio(loop_scope="session")
|
||||
async def test_get_random_cards_valid():
|
||||
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
|
||||
params = {"user_id": EXIST_USER}
|
||||
@@ -61,7 +61,7 @@ async def test_get_random_cards_valid():
|
||||
ACTIVE_CARDS_LESS_THAN_TEN = True
|
||||
pytest.skip(reason="The number of active cards is less than 10 in MongoDB")
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.asyncio(loop_scope="session")
|
||||
async def test_get_random_cards_randomness():
|
||||
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
|
||||
params = {"user_id": EXIST_USER}
|
||||
@@ -73,7 +73,7 @@ async def test_get_random_cards_randomness():
|
||||
if len(result1) == 10 and len(result2) == 10:
|
||||
assert result1 != result2
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.asyncio(loop_scope="session")
|
||||
async def test_get_random_cards_parallel_requests():
|
||||
if NO_ACTIVE_CARDS_STATUS:
|
||||
pytest.skip(reason="No active cards in MongoDB")
|
||||
|
||||
Reference in New Issue
Block a user