mirror of
https://github.com/wowlikon/LiB.git
synced 2026-02-04 04:31:09 +00:00
Добавление авторизации и фронтэнда
This commit is contained in:
+5
-4
@@ -1,23 +1,24 @@
|
||||
from fastapi import FastAPI
|
||||
from tests.mock_routers import books, authors, genres, relationships
|
||||
|
||||
from library_service.routers.misc import router as misc_router
|
||||
from tests.mock_routers import authors, books, genres, relationships
|
||||
|
||||
|
||||
def create_mock_app() -> FastAPI:
|
||||
"""Create FastAPI app with mock routers for testing"""
|
||||
"""Создание FastAPI app с моками роутеров для тестов"""
|
||||
app = FastAPI(
|
||||
title="Library API Test",
|
||||
description="Library API for testing without database",
|
||||
version="1.0.0",
|
||||
)
|
||||
|
||||
# Include mock routers
|
||||
# Подключение мок-роутеров
|
||||
app.include_router(books.router)
|
||||
app.include_router(authors.router)
|
||||
app.include_router(genres.router)
|
||||
app.include_router(relationships.router)
|
||||
|
||||
# Include real misc router (it doesn't use database)
|
||||
# Подключение реального misc роутера
|
||||
app.include_router(misc_router)
|
||||
|
||||
return app
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from fastapi import APIRouter, HTTPException
|
||||
|
||||
from tests.mocks.mock_storage import mock_storage
|
||||
|
||||
router = APIRouter(prefix="/authors", tags=["authors"])
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from fastapi import APIRouter, HTTPException
|
||||
|
||||
from tests.mocks.mock_storage import mock_storage
|
||||
|
||||
router = APIRouter(prefix="/books", tags=["books"])
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from fastapi import APIRouter, HTTPException
|
||||
|
||||
from tests.mocks.mock_storage import mock_storage
|
||||
|
||||
router = APIRouter(prefix="/genres", tags=["genres"])
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from fastapi import APIRouter, HTTPException
|
||||
|
||||
from tests.mocks.mock_storage import mock_storage
|
||||
|
||||
router = APIRouter(tags=["relations"])
|
||||
@@ -36,5 +37,4 @@ def get_authors_for_book(book_id: int):
|
||||
|
||||
@router.post("/relationships/genre-book")
|
||||
def add_genre_to_book(genre_id: int, book_id: int):
|
||||
# For tests that need genre functionality
|
||||
return {"genre_id": genre_id, "book_id": book_id}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from typing import Optional, List, Any
|
||||
from typing import Any, List
|
||||
|
||||
from tests.mocks.mock_storage import mock_storage
|
||||
|
||||
|
||||
@@ -8,20 +9,13 @@ class MockSession:
|
||||
def __init__(self):
|
||||
self.storage = mock_storage
|
||||
|
||||
def add(self, obj: Any):
|
||||
"""Mock add - not needed for our implementation"""
|
||||
pass
|
||||
def add(self, obj: Any): ...
|
||||
|
||||
def commit(self):
|
||||
"""Mock commit - not needed for our implementation"""
|
||||
pass
|
||||
def commit(self): ...
|
||||
|
||||
def refresh(self, obj: Any):
|
||||
"""Mock refresh - not needed for our implementation"""
|
||||
pass
|
||||
def refresh(self, obj: Any): ...
|
||||
|
||||
def get(self, model_class, pk: int):
|
||||
"""Mock get method to retrieve object by primary key"""
|
||||
if hasattr(model_class, "__name__"):
|
||||
model_name = model_class.__name__.lower()
|
||||
else:
|
||||
@@ -35,12 +29,9 @@ class MockSession:
|
||||
return self.storage.get_genre(pk)
|
||||
return None
|
||||
|
||||
def delete(self, obj: Any):
|
||||
"""Mock delete - handled in storage methods"""
|
||||
pass
|
||||
def delete(self, obj: Any): ...
|
||||
|
||||
def exec(self, statement):
|
||||
"""Mock exec method for queries"""
|
||||
return MockResult([])
|
||||
|
||||
|
||||
|
||||
+14
-16
@@ -1,4 +1,4 @@
|
||||
from typing import Dict, List, Optional
|
||||
from typing import Dict, List
|
||||
|
||||
|
||||
class MockStorage:
|
||||
@@ -15,7 +15,7 @@ class MockStorage:
|
||||
self.genre_id_counter = 1
|
||||
|
||||
def clear_all(self):
|
||||
"""Clear all data"""
|
||||
"""Очистка всех данных"""
|
||||
self.books.clear()
|
||||
self.authors.clear()
|
||||
self.genres.clear()
|
||||
@@ -33,7 +33,7 @@ class MockStorage:
|
||||
self.book_id_counter += 1
|
||||
return book
|
||||
|
||||
def get_book(self, book_id: int) -> Optional[dict]:
|
||||
def get_book(self, book_id: int) -> dict | None:
|
||||
return self.books.get(book_id)
|
||||
|
||||
def get_all_books(self) -> List[dict]:
|
||||
@@ -42,9 +42,9 @@ class MockStorage:
|
||||
def update_book(
|
||||
self,
|
||||
book_id: int,
|
||||
title: Optional[str] = None,
|
||||
description: Optional[str] = None,
|
||||
) -> Optional[dict]:
|
||||
title: str | None = None,
|
||||
description: str | None = None,
|
||||
) -> dict | None:
|
||||
if book_id not in self.books:
|
||||
return None
|
||||
book = self.books[book_id]
|
||||
@@ -54,7 +54,7 @@ class MockStorage:
|
||||
book["description"] = description
|
||||
return book
|
||||
|
||||
def delete_book(self, book_id: int) -> Optional[dict]:
|
||||
def delete_book(self, book_id: int) -> dict | None:
|
||||
if book_id not in self.books:
|
||||
return None
|
||||
book = self.books.pop(book_id)
|
||||
@@ -74,15 +74,15 @@ class MockStorage:
|
||||
self.author_id_counter += 1
|
||||
return author
|
||||
|
||||
def get_author(self, author_id: int) -> Optional[dict]:
|
||||
def get_author(self, author_id: int) -> dict | None:
|
||||
return self.authors.get(author_id)
|
||||
|
||||
def get_all_authors(self) -> List[dict]:
|
||||
return list(self.authors.values())
|
||||
|
||||
def update_author(
|
||||
self, author_id: int, name: Optional[str] = None
|
||||
) -> Optional[dict]:
|
||||
self, author_id: int, name: str | None = None
|
||||
) -> dict | None:
|
||||
if author_id not in self.authors:
|
||||
return None
|
||||
author = self.authors[author_id]
|
||||
@@ -90,7 +90,7 @@ class MockStorage:
|
||||
author["name"] = name
|
||||
return author
|
||||
|
||||
def delete_author(self, author_id: int) -> Optional[dict]:
|
||||
def delete_author(self, author_id: int) -> dict | None:
|
||||
if author_id not in self.authors:
|
||||
return None
|
||||
author = self.authors.pop(author_id)
|
||||
@@ -107,15 +107,13 @@ class MockStorage:
|
||||
self.genre_id_counter += 1
|
||||
return genre
|
||||
|
||||
def get_genre(self, genre_id: int) -> Optional[dict]:
|
||||
def get_genre(self, genre_id: int) -> dict | None:
|
||||
return self.genres.get(genre)
|
||||
|
||||
def get_all_authors(self) -> List[dict]:
|
||||
return list(self.authors.values())
|
||||
|
||||
def update_genre(
|
||||
self, genre_id: int, name: Optional[str] = None
|
||||
) -> Optional[dict]:
|
||||
def update_genre(self, genre_id: int, name: str | None = None) -> dict | None:
|
||||
if genre_id not in self.genres:
|
||||
return None
|
||||
genre = self.genres[genre_id]
|
||||
@@ -123,7 +121,7 @@ class MockStorage:
|
||||
genre["name"] = name
|
||||
return genre
|
||||
|
||||
def delete_genre(self, genre_id: int) -> Optional[dict]:
|
||||
def delete_genre(self, genre_id: int) -> dict | None:
|
||||
if genre_id not in self.genres:
|
||||
return None
|
||||
genre = self.genres.pop(genre_id)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from tests.mock_app import mock_app
|
||||
from tests.mocks.mock_storage import mock_storage
|
||||
|
||||
@@ -8,7 +9,6 @@ client = TestClient(mock_app)
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_database():
|
||||
"""Clear mock storage before each test"""
|
||||
mock_storage.clear_all()
|
||||
yield
|
||||
mock_storage.clear_all()
|
||||
@@ -29,7 +29,6 @@ def test_create_author():
|
||||
|
||||
|
||||
def test_list_authors():
|
||||
# First create an author
|
||||
client.post("/authors", json={"name": "Test Author"})
|
||||
|
||||
response = client.get("/authors")
|
||||
@@ -42,7 +41,6 @@ def test_list_authors():
|
||||
|
||||
|
||||
def test_get_existing_author():
|
||||
# First create an author
|
||||
client.post("/authors", json={"name": "Test Author"})
|
||||
|
||||
response = client.get("/authors/1")
|
||||
@@ -63,7 +61,6 @@ def test_get_not_existing_author():
|
||||
|
||||
|
||||
def test_update_author():
|
||||
# First create an author
|
||||
client.post("/authors", json={"name": "Test Author"})
|
||||
|
||||
response = client.get("/authors/1")
|
||||
@@ -84,10 +81,7 @@ def test_update_not_existing_author():
|
||||
|
||||
|
||||
def test_delete_author():
|
||||
# First create an author
|
||||
client.post("/authors", json={"name": "Test Author"})
|
||||
|
||||
# Update it first
|
||||
client.put("/authors/1", json={"name": "Updated Author"})
|
||||
|
||||
response = client.get("/authors/1")
|
||||
|
||||
+6
-18
@@ -1,5 +1,6 @@
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from tests.mock_app import mock_app
|
||||
from tests.mocks.mock_storage import mock_storage
|
||||
|
||||
@@ -8,7 +9,6 @@ client = TestClient(mock_app)
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_database():
|
||||
"""Clear mock storage before each test"""
|
||||
mock_storage.clear_all()
|
||||
yield
|
||||
mock_storage.clear_all()
|
||||
@@ -35,9 +35,7 @@ def test_create_book():
|
||||
|
||||
|
||||
def test_list_books():
|
||||
# First create a book
|
||||
client.post(
|
||||
"/books", json={"title": "Test Book", "description": "Test Description"}
|
||||
client.post("/books", json={"title": "Test Book", "description": "Test Description"}
|
||||
)
|
||||
|
||||
response = client.get("/books")
|
||||
@@ -50,9 +48,7 @@ def test_list_books():
|
||||
|
||||
|
||||
def test_get_existing_book():
|
||||
# First create a book
|
||||
client.post(
|
||||
"/books", json={"title": "Test Book", "description": "Test Description"}
|
||||
client.post("/books", json={"title": "Test Book", "description": "Test Description"}
|
||||
)
|
||||
|
||||
response = client.get("/books/1")
|
||||
@@ -74,9 +70,7 @@ def test_get_not_existing_book():
|
||||
|
||||
|
||||
def test_update_book():
|
||||
# First create a book
|
||||
client.post(
|
||||
"/books", json={"title": "Test Book", "description": "Test Description"}
|
||||
client.post("/books", json={"title": "Test Book", "description": "Test Description"}
|
||||
)
|
||||
|
||||
response = client.get("/books/1")
|
||||
@@ -102,14 +96,8 @@ def test_update_not_existing_book():
|
||||
|
||||
|
||||
def test_delete_book():
|
||||
# First create a book
|
||||
client.post(
|
||||
"/books", json={"title": "Test Book", "description": "Test Description"}
|
||||
)
|
||||
|
||||
# Update it first
|
||||
client.put(
|
||||
"/books/1", json={"title": "Updated Book", "description": "Updated Description"}
|
||||
client.post("/books", json={"title": "Test Book", "description": "Test Description"})
|
||||
client.put("/books/1", json={"title": "Updated Book", "description": "Updated Description"}
|
||||
)
|
||||
|
||||
response = client.get("/books/1")
|
||||
|
||||
+10
-22
@@ -1,6 +1,8 @@
|
||||
import pytest
|
||||
from datetime import datetime
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from tests.mock_app import mock_app
|
||||
from tests.mocks.mock_storage import mock_storage
|
||||
|
||||
@@ -9,20 +11,15 @@ client = TestClient(mock_app)
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_database():
|
||||
"""Setup and cleanup mock database for each test"""
|
||||
# Clear data before each test
|
||||
mock_storage.clear_all()
|
||||
yield
|
||||
# Clear data after each test (optional, but good practice)
|
||||
mock_storage.clear_all()
|
||||
|
||||
|
||||
# Test the main page of the application
|
||||
def test_main_page():
|
||||
response = client.get("/") # Send GET request to the main page
|
||||
response = client.get("/api")
|
||||
try:
|
||||
content = response.content.decode("utf-8") # Decode response content
|
||||
# Find indices of key elements in the content
|
||||
content = response.content.decode("utf-8")
|
||||
title_idx = content.index("Welcome to ")
|
||||
description_idx = content.index("Description: ")
|
||||
version_idx = content.index("Version: ")
|
||||
@@ -38,25 +35,16 @@ def test_main_page():
|
||||
assert content[time_idx + 1] != "<", "Time not provided"
|
||||
assert content[status_idx + 1] != "<", "Status not provided"
|
||||
except Exception as e:
|
||||
print(f"Error: {e}") # Print error if an exception occurs
|
||||
assert False, "Unexpected error" # Force test failure on unexpected error
|
||||
print(f"Error: {e}")
|
||||
assert False, "Unexpected error"
|
||||
|
||||
|
||||
# Test application info endpoint
|
||||
def test_app_info_test():
|
||||
response = client.get("/api/info") # Send GET request to the info endpoint
|
||||
response = client.get("/api/info")
|
||||
assert response.status_code == 200, "Invalid response status"
|
||||
assert response.json()["status"] == "ok", "Status not ok"
|
||||
assert response.json()["app_info"]["title"] != "", "Title not provided"
|
||||
assert response.json()["app_info"]["description"] != "", "Description not provided"
|
||||
assert response.json()["app_info"]["version"] != "", "Version not provided"
|
||||
# Check time difference
|
||||
assert (
|
||||
0
|
||||
< (
|
||||
datetime.now() - datetime.fromisoformat(response.json()["server_time"])
|
||||
).total_seconds()
|
||||
), "Negative time difference"
|
||||
assert (
|
||||
datetime.now() - datetime.fromisoformat(response.json()["server_time"])
|
||||
).total_seconds() < 1, "Time difference too large"
|
||||
assert (0 < (datetime.now() - datetime.fromisoformat(response.json()["server_time"])).total_seconds()), "Negative time difference"
|
||||
assert (datetime.now() - datetime.fromisoformat(response.json()["server_time"])).total_seconds() < 1, "Time difference too large"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from tests.mock_app import mock_app
|
||||
from tests.mocks.mock_storage import mock_storage
|
||||
|
||||
@@ -8,7 +9,6 @@ client = TestClient(mock_app)
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_database():
|
||||
"""Clear mock storage before each test"""
|
||||
mock_storage.clear_all()
|
||||
yield
|
||||
mock_storage.clear_all()
|
||||
@@ -30,28 +30,18 @@ def make_genrebook_relationship(genre_id, book_id):
|
||||
|
||||
|
||||
def test_prepare_data():
|
||||
# Create books
|
||||
assert client.post(
|
||||
"/books", json={"title": "Test Book 1", "description": "Test Description 1"}
|
||||
).status_code == 200
|
||||
assert client.post(
|
||||
"/books", json={"title": "Test Book 2", "description": "Test Description 2"}
|
||||
).status_code == 200
|
||||
assert client.post(
|
||||
"/books", json={"title": "Test Book 3", "description": "Test Description 3"}
|
||||
).status_code == 200
|
||||
assert (client.post("/books", json={"title": "Test Book 1", "description": "Test Description 1"}).status_code == 200)
|
||||
assert (client.post("/books", json={"title": "Test Book 2", "description": "Test Description 2"}).status_code == 200)
|
||||
assert (client.post("/books", json={"title": "Test Book 3", "description": "Test Description 3"}).status_code == 200)
|
||||
|
||||
# Create authors
|
||||
assert client.post("/authors", json={"name": "Test Author 1"}).status_code == 200
|
||||
assert client.post("/authors", json={"name": "Test Author 2"}).status_code == 200
|
||||
assert client.post("/authors", json={"name": "Test Author 3"}).status_code == 200
|
||||
|
||||
# Create genres
|
||||
assert client.post("/genres", json={"name": "Test Genre 1"}).status_code == 200
|
||||
assert client.post("/genres", json={"name": "Test Genre 2"}).status_code == 200
|
||||
assert client.post("/genres", json={"name": "Test Genre 3"}).status_code == 200
|
||||
|
||||
# Create relationships
|
||||
make_authorbook_relationship(1, 1)
|
||||
make_authorbook_relationship(2, 1)
|
||||
make_authorbook_relationship(1, 2)
|
||||
@@ -63,8 +53,8 @@ def test_prepare_data():
|
||||
make_genrebook_relationship(2, 3)
|
||||
make_genrebook_relationship(3, 3)
|
||||
|
||||
|
||||
def test_get_book_authors():
|
||||
# Setup test data
|
||||
test_prepare_data()
|
||||
|
||||
response1 = client.get("/books/1/authors")
|
||||
@@ -91,7 +81,6 @@ def test_get_book_authors():
|
||||
|
||||
|
||||
def test_get_author_books():
|
||||
# Setup test data
|
||||
test_prepare_data()
|
||||
|
||||
response1 = client.get("/authors/1/books")
|
||||
|
||||
Reference in New Issue
Block a user