Compare commits

..
Author SHA1 Message Date
Gustavo Henrique Santos Souza de Miranda 77e191f480 test(entry_service): add test for creating an entry without photos
This commit adds a unit test to ensure that the EntryService's
`create` method correctly handles cases where an empty list of photos
is provided.

It verifies that the entry is created successfully and that the
`photos` relationship is an empty list, confirming the feature's
flexibility.
2025-07-20 16:03:45 -03:00
Gustavo Henrique Santos Souza de Miranda 3c7925cb1c test(entry_service): add a failure case test for create method
This commit adds a unit test for an important "unhappy path" in the
EntryService's `create` method.

It specifically verifies that the method gracefully returns `None`
when provided with a `travel_diary_id` that does not exist in the
database, ensuring the initial guard clause works as expected.
2025-07-20 15:21:49 -03:00
Gustavo Henrique Santos Souza de Miranda c4dceda942 test(entry_service): add unit test for creating a new entry
This commit introduces the first unit test for the EntryService,
covering the "happy path" for the `create` method.

It verifies that a new entry is correctly persisted to the database,
including its relationship with associated Photo objects. The test
leverages fixtures to create an isolated, in-memory database
populated with the necessary dependencies.
2025-07-20 03:35:22 -03:00
Gustavo Henrique Miranda 4d87ae1b90 Merge pull request #61 from gmbrax/fix/relative-imports
Fix/relative imports
2025-07-20 03:27:31 -03:00
Gustavo Henrique Mirandaandcoderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> e1add84537 Update src/pilgrim/database.py
Remove Debug message

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-07-20 03:23:37 -03:00
Gustavo Henrique Santos Souza de Miranda 2ba1cbd0a6 Fix the declarative_base import to the newer way 2025-07-20 03:10:13 -03:00
Gustavo Henrique Santos Souza de Miranda eed16f34c1 Simplify the pyproject.toml 2025-07-20 02:47:05 -03:00
Gustavo Henrique Santos Souza de Miranda 06ee08b201 Fix all imports to be absolute and not relative 2025-07-20 02:46:46 -03:00
10 changed files with 134 additions and 83 deletions
+28 -33
View File
@@ -1,36 +1,31 @@
[build-system] [build-system]
requires = ["hatchling"] requires = ["hatchling"]
build-backend = "hatchling.build" build-backend = "hatchling.build"
[project]
name = "pilgrim"
version = "0.0.4"
authors = [
{ name="Gustavo Henrique Santos Souza de Miranda", email="gustavohssmiranda@gmail.com" }
]
description = "Pilgrim's Travel Log"
readme = "README.md"
requires-python = ">=3.10"
classifiers = [
"Programming Language :: Python :: 3",
"License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",
]
dependencies = [
"sqlalchemy",
"textual",
"tomli",
"tomli_w"
]
[project] [project.urls]
name = "Pilgrim" Homepage = "https://github.com/gmbrax/Pilgrim/"
version = "0.0.4" Issues = "https://github.com/gmbrax/Pilgrim/issues"
authors = [
{ name="Gustavo Henrique Santos Souza de Miranda", email="gustavohssmiranda@gmail.com" }
]
description = "Pilgrim's Travel Log"
readme = "README.md"
requires-python = ">=3.10"
classifiers = [
"Programming Language :: Python :: 3",
"License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",
]
dependencies = [
"sqlalchemy",
"textual",
"tomli",
"tomli_w"
[project.scripts]
] pilgrim = "pilgrim.command:main"
[template.plugins.default]
src-layout = true
[project.urls]
Homepage = "https://github.com/gmbrax/Pilgrim/"
Issues = "https://github.com/gmbrax/Pilgrim/issues"
[tool.hatch.build.targets.wheel]
packages = ["src/pilgrim"]
[project.scripts]
pilgrim = "pilgrim:main"
+1 -1
View File
@@ -1,5 +1,5 @@
from sqlalchemy import create_engine from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import declarative_base
from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import sessionmaker
from pathlib import Path from pathlib import Path
import os import os
+2 -1
View File
@@ -4,7 +4,8 @@ from pilgrim.models.photo_in_entry import photo_entry_association
from sqlalchemy import Column, Integer, String, ForeignKey, DateTime from sqlalchemy import Column, Integer, String, ForeignKey, DateTime
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from ..database import Base from pilgrim.database import Base
class Entry(Base): class Entry(Base):
+2 -1
View File
@@ -7,7 +7,8 @@ from sqlalchemy.orm import relationship
from sqlalchemy.sql.schema import Index from sqlalchemy.sql.schema import Index
from pilgrim.models.photo_in_entry import photo_entry_association from pilgrim.models.photo_in_entry import photo_entry_association
from ..database import Base from pilgrim.database import Base
class Photo(Base): class Photo(Base):
+1 -1
View File
@@ -1,6 +1,6 @@
from sqlalchemy import Table, Column, Integer, ForeignKey from sqlalchemy import Table, Column, Integer, ForeignKey
from ..database import Base from pilgrim.database import Base
photo_entry_association = Table('photo_entry_association', Base.metadata, photo_entry_association = Table('photo_entry_association', Base.metadata,
Column('id', Integer, primary_key=True, autoincrement=True), Column('id', Integer, primary_key=True, autoincrement=True),
+3 -2
View File
@@ -3,10 +3,11 @@ from typing import Any
from sqlalchemy import Column, Integer, String, UniqueConstraint from sqlalchemy import Column, Integer, String, UniqueConstraint
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from .. import database from pilgrim.database import Base
class TravelDiary(database.Base):
class TravelDiary(Base):
__tablename__ = "travel_diaries" __tablename__ = "travel_diaries"
id = Column(Integer, primary_key=True) id = Column(Integer, primary_key=True)
name = Column(String, nullable=False) name = Column(String, nullable=False)
+3 -3
View File
@@ -1,9 +1,9 @@
from datetime import datetime from datetime import datetime
from typing import List from typing import List
from ..models.entry import Entry from pilgrim.models.entry import Entry
from ..models.travel_diary import TravelDiary from pilgrim.models.travel_diary import TravelDiary
from ..models.photo import Photo # ✨ Importe o modelo Photo from pilgrim.models.photo import Photo # ✨ Importe o modelo Photo
class EntryService: class EntryService:
+1 -1
View File
@@ -6,7 +6,7 @@ from pathlib import Path
from pilgrim.utils import DirectoryManager from pilgrim.utils import DirectoryManager
from sqlalchemy.exc import IntegrityError from sqlalchemy.exc import IntegrityError
from ..models.travel_diary import TravelDiary from pilgrim.models.travel_diary import TravelDiary
class TravelDiaryService: class TravelDiaryService:
+93
View File
@@ -0,0 +1,93 @@
import pytest
from datetime import datetime
from unittest.mock import Mock
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from pilgrim.database import Base
from pilgrim.models.travel_diary import TravelDiary
from pilgrim.models.entry import Entry
from pilgrim.models.photo import Photo
from pilgrim.service.entry_service import EntryService
@pytest.fixture(scope="function")
def db_session():
engine = create_engine("sqlite:///:memory:")
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
yield session
session.close()
Base.metadata.drop_all(engine)
@pytest.fixture
def populated_db_session(db_session):
travel_diary = TravelDiary(name="My Travel Diary", directory_name="viagem-teste")
db_session.add(travel_diary)
db_session.commit()
return db_session
def test_create_entry_successfully(populated_db_session):
session = populated_db_session
service = EntryService(session)
diary_id = 1 # Sabemos que o ID é 1 por causa da nossa fixture
title = "Primeiro Dia na Praia"
text = "O dia foi ensolarado e o mar estava ótimo."
date = datetime(2025, 7, 20)
photos = [Photo(filepath="/path/to/photo1.jpg",name="Photo 1",photo_hash="hash_12345678",fk_travel_diary_id=diary_id), Photo(filepath="/path/to/photo2.jpg",name="Photo 1",photo_hash="hash_87654321",fk_travel_diary_id=diary_id)]
created_entry = service.create(
travel_diary_id=diary_id,
title=title,
text=text,
date=date,
photos=photos
)
assert created_entry is not None
assert created_entry.id is not None # Garante que foi salvo no BD e tem um ID
assert created_entry.title == title
assert created_entry.text == text
assert len(created_entry.photos) == 2
assert created_entry.photos[0].filepath == "/path/to/photo1.jpg"
entry_in_db = session.query(Entry).filter_by(id=created_entry.id).one()
assert entry_in_db.title == "Primeiro Dia na Praia"
def test_create_entry_fails_when_diary_id_is_invalid(db_session):
session = db_session
service = EntryService(session)
invalid_id = 666
result = service.create(
travel_diary_id=invalid_id,
title="Título de Teste",
text="Texto de Teste",
date=datetime(2025, 7, 20),
photos=[]
)
assert result is None
def test_create_entry_successfully_without_photo(populated_db_session):
session = populated_db_session
service = EntryService(session)
diary_id = 1 # Sabemos que o ID é 1 por causa da nossa fixture
title = "Primeiro Dia na Praia"
text = "O dia foi ensolarado e o mar estava ótimo."
date = datetime(2025, 7, 20)
photos = []
created_entry = service.create(
travel_diary_id=diary_id,
title=title,
text=text,
date=date,
photos=photos
)
assert created_entry is not None
assert created_entry.id is not None # Garante que foi salvo no BD e tem um ID
assert created_entry.title == title
assert created_entry.text == text
assert len(created_entry.photos) == 0
entry_in_db = session.query(Entry).filter_by(id=created_entry.id).one()
assert entry_in_db.title == "Primeiro Dia na Praia"
-40
View File
@@ -1,40 +0,0 @@
import pytest
from unittest.mock import Mock # A ferramenta para criar nosso "dublê"
from pathlib import Path
from sqlalchemy import inspect, Column, Integer, String
from sqlalchemy.orm import Session
from pilgrim.database import Database,Base
class MockUser(Base):
__tablename__ = 'mock_users'
id = Column(Integer, primary_key=True)
name = Column(String)
@pytest.fixture
def db_instance(tmp_path: Path):
fake_db_path = tmp_path / "test_pilgrim.db"
mock_config_manager = Mock()
mock_config_manager.database_url = str(fake_db_path)
db = Database(mock_config_manager)
return db, fake_db_path
def test_create_database(db_instance):
db, fake_db_path = db_instance
db.create()
assert fake_db_path.exists()
def test_table_creation(db_instance):
db, _ = db_instance
db.create()
inspector = inspect(db.engine)
assert "mock_users" in inspector.get_table_names()
def test_session_returned_corectly(db_instance):
db, _ = db_instance
session = db.session()
assert isinstance(session, Session)
session.close()