Skip to content

Add communities database model #19

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions app/main.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import logging
from contextlib import asynccontextmanager

from fastapi import FastAPI , Depends, HTTPException
from fastapi.exceptions import RequestValidationError
from httpx import AsyncClient
from typing import List
from sqlmodel.ext.asyncio.session import AsyncSession
from fastapi import FastAPI

from app.services.database.database import init_db, get_session, TestEntry, AsyncSessionLocal
from app.routers.router import setup_router as setup_router_v2
Expand Down
11 changes: 11 additions & 0 deletions app/services/database/communities.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from typing import Optional

from sqlmodel import SQLModel, Field

class Community(SQLModel, table=True):
__tablename__ = "communities"

id: Optional[int] = Field(default=None, primary_key=True)
username: str
email: str
password: str
11 changes: 6 additions & 5 deletions app/services/database/database.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
# database.py
import logging
import os
import logging
from typing import AsyncGenerator

from sqlmodel import SQLModel, create_engine, Field
from sqlalchemy.ext.asyncio import AsyncEngine
from sqlalchemy.orm import sessionmaker

from sqlmodel import SQLModel, create_engine, Field
from sqlmodel.ext.asyncio.session import AsyncSession
from sqlalchemy.ext.asyncio import AsyncEngine

import app.services.database.communities
import app.services.database.libraries

logger = logging.getLogger(__name__)
logger = logging.getLogger(__name__)

# --- Configuração do Banco de Dados ---
# 'sqlite+aiosqlite' para suporte assíncrono com SQLite
Expand Down
12 changes: 8 additions & 4 deletions app/services/database/libraries.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
from sqlmodel import SQLModel, Field
from typing import Optional
from sqlmodel import SQLModel, Field, Relationship

class Libraries(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
class Library(SQLModel, table=True):
__tablename__ = "libraries"

id: Optional[int] = Field(default=None, primary_key=True)
library_name: str
user_email: str
releases_url: str
logo: str
logo: str
community_id: Optional[int] = Field(default=None, foreign_key="communities.id")
81 changes: 35 additions & 46 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,35 +1,22 @@
import os
from collections.abc import AsyncGenerator
from unittest.mock import AsyncMock, patch
from unittest.mock import AsyncMock

import pytest
import pytest_asyncio
from fastapi import FastAPI
from httpx import ASGITransport, AsyncClient



from app.main import app , get_db_session
from app.main import app as fastapi_app, get_db_session
from sqlmodel import SQLModel, create_engine
from sqlmodel.ext.asyncio.session import AsyncSession
from sqlalchemy.ext.asyncio import AsyncEngine
from sqlalchemy.orm import sessionmaker

# Importar todos os modelos SQLModel a serem usados (necessários para as validações de modelo)
from app.services.database.database import TestEntry
import app.services.database.communities
import app.services.database.libraries

@pytest.fixture
def test_app() -> FastAPI:
# Create a mock schema checker
mock_schema_checker = AsyncMock()
mock_schema_checker.validate = AsyncMock(return_value=None)
mock_schema_checker.start = AsyncMock(return_value=None)

# Add the mock to the app
app.schema_checker = mock_schema_checker
return app


# --- Configurações do Banco de Dados em Memória para Testes ---
# Usamos engine e AsyncSessionLocal apenas para os testes.
# Isso garante que os testes são isolados e usam o banco de dados em memória.
Expand All @@ -38,50 +25,52 @@ def test_app() -> FastAPI:
test_engine: AsyncEngine = AsyncEngine(create_engine(TEST_DATABASE_URL, echo=False, future=True))

# Fábrica de sessões para os testes
TestSessionLocal = sessionmaker(
test_engine, class_=AsyncSession, expire_on_commit=False
)
TestSessionLocal = sessionmaker(test_engine, class_=AsyncSession, expire_on_commit=False)

async def init_test_db():
"""
Inicializa o banco de dados em memória para testes, criando todas as tabelas.
"""
async with test_engine.begin() as conn:
# Cria as tabelas para todos os modelos SQLModel na base de teste
await conn.run_sync(SQLModel.metadata.create_all)

async def override_get_db_session() -> AsyncGenerator[AsyncSession, None]:
async def get_db_session_test() -> AsyncGenerator[AsyncSession, None]:
"""
Sobrescreve a dependência get_db_session para usar a sessão de teste.
"""
async with TestSessionLocal() as session:
yield session

@pytest_asyncio.fixture(scope="function", autouse=True)
async def setup_database():
async with test_engine.begin() as conn:
await conn.run_sync(SQLModel.metadata.create_all)
yield
async with test_engine.begin() as conn:
await conn.run_sync(SQLModel.metadata.drop_all)

@pytest_asyncio.fixture(scope="function")
async def session() -> AsyncGenerator[AsyncSession, None]:
async_session_generator = get_db_session_test()
session = await anext(async_session_generator)
yield session
await session.close()

@pytest.fixture
def test_app() -> FastAPI:
# Create a mock schema checker
mock_schema_checker = AsyncMock()
mock_schema_checker.validate = AsyncMock(return_value=None)
mock_schema_checker.start = AsyncMock(return_value=None)

# Add the mock to the app
fastapi_app.schema_checker = mock_schema_checker
fastapi_app.dependency_overrides[get_db_session] = get_db_session_test
yield fastapi_app
fastapi_app.dependency_overrides.clear()

@pytest_asyncio.fixture(scope='function')
async def async_client(test_app: FastAPI) -> AsyncGenerator[AsyncClient, None]:
"""
Cria um cliente assíncrono para testes, com o banco de dados em memória e
dependências sobrescritas.
"""
# Sobrescreve a dependência get_db_session no app principal
test_app.dependency_overrides[get_db_session] = override_get_db_session


# Inicializa o banco de dados em memória e cria as tabelas para cada função de teste
await init_test_db()

async with AsyncClient(
transport=ASGITransport(app=test_app), base_url='http://test'
) as client:
async with AsyncClient(transport=ASGITransport(app=test_app), base_url='http://test') as client:
yield client

# Limpa as tabelas do banco de dados em após cada teste.
# para SQLite in-memory não é necessário, mas é um bom padrão para outros DBs.
async with test_engine.begin() as conn:
await conn.run_sync(SQLModel.metadata.drop_all)
# Limpa as sobrescritas de dependência.
test_app.dependency_overrides.clear()



@pytest.fixture
Expand Down
27 changes: 27 additions & 0 deletions tests/test_communities.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import pytest

from sqlmodel import select
from sqlmodel.ext.asyncio.session import AsyncSession

from app.services.database.communities import Community


@pytest.mark.asyncio
async def test_insert_communities(session: AsyncSession):
community = Community(
username="admin",
email="[email protected]",
password="@teste123",
)
session.add(community)
await session.commit()
await session.refresh(community)

statement = select(Community).where(Community.username == "admin")
result = await session.exec(statement)
found = result.first()

assert found is not None
assert found.username == "admin"
assert found.email == "[email protected]"
assert found.password == "@teste123"
6 changes: 4 additions & 2 deletions tests/test_healthcheck.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import pytest
from fastapi import status
from httpx import AsyncClient
from typing import Mapping


@pytest.mark.asyncio
async def test_healthcheck_endpoint(async_client, mock_headers):
async def test_healthcheck_endpoint(async_client: AsyncClient, mock_headers: Mapping[str, str]):
"""Test the healthcheck endpoint returns correct status and version."""
#response = await async_client.get('/v2/healthcheck', headers=mock_headers)
response = await async_client.get('/api/healthcheck', headers=mock_headers)
Expand All @@ -13,7 +15,7 @@ async def test_healthcheck_endpoint(async_client, mock_headers):


@pytest.mark.asyncio
async def test_healthcheck_endpoint_without_auth(async_client):
async def test_healthcheck_endpoint_without_auth(async_client: AsyncClient):
"""Test the healthcheck endpoint without authentication headers."""
#response = await async_client.get('/v2/healthcheck')
response = await async_client.get('/api/healthcheck')
Expand Down
39 changes: 39 additions & 0 deletions tests/test_libraries.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import pytest
import pytest_asyncio

from sqlmodel import select
from sqlmodel.ext.asyncio.session import AsyncSession

from app.services.database.communities import Community
from app.services.database.libraries import Library

@pytest_asyncio.fixture
async def community(session: AsyncSession):
community = Community(username="admin", email="[email protected]", password="123")
session.add(community)
await session.commit()
await session.refresh(community)
return community

@pytest.mark.asyncio
async def test_insert_libraries(session: AsyncSession, community: Community):
library = Library(
library_name="DevOps",
user_email="[email protected]",
releases_url="http://teste.com",
logo="logo",
community_id=community.id,
)
session.add(library)
await session.commit()

statement = select(Library).where(Library.library_name == "DevOps")
result = await session.exec(statement)
found = result.first()

assert found is not None
assert found.library_name == "DevOps"
assert found.user_email == "[email protected]"
assert found.releases_url == "http://teste.com"
assert found.logo == "logo"
assert found.community_id == community.id