Compare commits

..
Author SHA1 Message Date
Gustavo Henrique Santos Souza de Miranda 53e8b36a42 Add fixture and tests for the backup service 2025-07-24 22:56:43 -03:00
Gustavo Henrique Miranda 7faab93dfe Update CHANGELOG.md
Add the 0.0.5 changes into the changelog
2025-07-24 21:52:28 -03:00
Gustavo Henrique Miranda 34821bfedb Merge pull request #82 from gmbrax/refactor/remove-mocks
Remove the unused mock services
2025-07-24 21:12:32 -03:00
3 changed files with 135 additions and 35 deletions
+55 -34
View File
@@ -6,63 +6,84 @@ The format is based on Keep a Changelog, and this project adheres to Semantic Ve
## Unreleased ## Unreleased
## Planned ## Planned
* Installation Method 1 (repository compilation) * Restore from backup functionality
* Organization of trips by date, location, or theme * Organization of trips by date, location, or theme
* Enhanced photo management features * Enhanced photo management features
* Search functionality * Search functionality
* Export features * Export features
* Testing implementation * UI Testing with Textual Pilot
## [0.0.5] - 2025-07-24
### Added
* **Backup Feature:** Introduced a full backup feature to export the database and all photos to a single ZIP file.
* **Diary Settings Screen:** Added a dedicated settings screen per diary, accessible with the 's' key from the diary list.
* **Advanced Deletion Options:** The new settings screen allows for deleting the entire diary, all of its entries, or all of its photos.
* **Confirmation Modals:** Added confirmation modals that require the user to type the diary's name to proceed with critical delete operations, preventing accidental data loss.
* **Comprehensive Test Suite:** Implemented a robust unit and integration test suite for the entire backend (services, models, utils, application), achieving high code coverage and ensuring stability.
### Changed
* **Architectural Refactor:** Service methods were refactored to be transactional, allowing for more complex operations to be executed safely and atomically.
* **Configuration:** The "auto-open diary on startup" setting is now managed and persisted via the `config.toml` file.
* **Project Structure:** Standardized project metadata and build configuration in `pyproject.toml` and converted all imports to use a consistent absolute path structure.
### Fixed
* **Directory Name Sanitization:** Fixed a bug where directory names were not correctly sanitized, now properly handling accented and special characters by using transliteration.
* **Data Integrity:** Enforced `NOT NULL` constraints on `title` and `date` fields for entries in the database, preventing the creation of entries with invalid data.
### Removed
* **Obsolete Mocks:** Removed old and unused mock service files from the production codebase.
## [0.0.4] - 2025-07-19 ## [0.0.4] - 2025-07-19
### Added ### Added
* Support for creating new diaries asynchronously, with an option to automatically open the newly created diary * Support for creating new diaries asynchronously, with an option to automatically open the newly created diary.
* Unified "Enter" key support for saving or creating diaries across relevant modals * Unified "Enter" key support for saving or creating diaries across relevant modals.
* Automatic diary list refresh when returning to the diary screen * Automatic diary list refresh when returning to the diary screen.
* Application configuration management with a new centralized config system * Application configuration management with a new centralized config system.
* Database location and initialization now configurable via the new config manager * Database location and initialization now configurable via the new config manager.
* Automatic migration of database file to the configuration directory * Automatic migration of database file to the configuration directory.
* Display of database URL on application startup for transparency * Display of database URL on application startup for transparency.
* Duplicate photo detection before photo creation to prevent redundant entries * Duplicate photo detection before photo creation to prevent redundant entries.
* Photo hash indexing to improve photo lookup performance * Photo hash indexing to improve photo lookup performance.
### Changed ### Changed
* Enhanced feedback and validation when editing or creating diary names * Enhanced feedback and validation when editing or creating diary names.
* Streamlined and unified save logic for diary modals, reducing duplicated behavior * Streamlined and unified save logic for diary modals, reducing duplicated behavior.
* About screen now displays the actual installed application version dynamically * About screen now displays the actual installed application version dynamically.
* Sidebar and photo-related UI text updated to remove emoji icons for a cleaner appearance * Sidebar and photo-related UI text updated to remove emoji icons for a cleaner appearance.
* Sidebar layout and scrolling behavior improved for better usability * Sidebar layout and scrolling behavior improved for better usability.
* Photo hash generation now relies on existing service-provided hashes instead of local computation * Photo hash generation now relies on existing service-provided hashes instead of local computation.
### Improved ### Improved
* Enhanced feedback and validation when editing or creating diary names * Enhanced feedback and validation when editing or creating diary names.
* Streamlined and unified save logic for diary modals, reducing duplicated behavior * Streamlined and unified save logic for diary modals, reducing duplicated behavior.
* Sidebar layout and scrolling behavior for better usability * Sidebar layout and scrolling behavior for better usability.
## [0.0.3] - 2025-07-07 ## [0.0.3] - 2025-07-07
### Changed ### Changed
* Removed the dependency on textual-dev from pyproject.toml * Removed the dependency on textual-dev from pyproject.toml.
## [0.0.2] - 2025-07-07 ## [0.0.2] - 2025-07-07
### Changed ### Changed
* Changed the license in pyproject.toml to BSD * Changed the license in pyproject.toml to BSD.
## [0.0.1] - 2025-07-06 ## [0.0.1] - 2025-07-06
### Added ### Added
* Initial alpha release of Pilgrim travel diary application * Initial alpha release of Pilgrim travel diary application.
* Create and edit travel diaries * Create and edit travel diaries.
* Create and edit diary entries * Create and edit diary entries.
* Photo ingestion system * Photo ingestion system.
* Photo addition and reference via sidebar * Photo addition and reference via sidebar.
* Text User Interface (TUI) built with Textual framework * Text User Interface (TUI) built with Textual framework.
* Pre-compiled binary installation method (Method 2) * Pre-compiled binary installation method (Method 2).
* Support for Linux operating systems * Support for Linux operating systems.
* Basic project documentation (README) * Basic project documentation (README).
### Known Issues ### Known Issues
* Installation Method 1 not yet implemented * Installation Method 1 not yet implemented.
* No testing suite implemented yet * No testing suite implemented yet.
* Some features may be unstable in an alpha version * Some features may be unstable in an alpha version.
+40
View File
@@ -1,3 +1,6 @@
from pathlib import Path
from unittest.mock import patch
import pytest import pytest
from sqlalchemy import create_engine from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import sessionmaker
@@ -5,6 +8,8 @@ from sqlalchemy.orm import sessionmaker
from pilgrim.database import Base from pilgrim.database import Base
from pilgrim.models.travel_diary import TravelDiary from pilgrim.models.travel_diary import TravelDiary
from pilgrim.models.photo import Photo from pilgrim.models.photo import Photo
from pilgrim.utils import DirectoryManager
# Todos os imports necessários para as fixtures devem estar aqui # Todos os imports necessários para as fixtures devem estar aqui
# ... # ...
@@ -62,3 +67,38 @@ def session_with_photos(session_with_one_diary):
session.commit() session.commit()
return session, [photo1, photo2] return session, [photo1, photo2]
@pytest.fixture
def backup_test_env_files_only(tmp_path):
fake_config_dir = tmp_path / "config"
fake_diaries_root = tmp_path / "diaries"
fake_db_path = fake_config_dir / "database.db"
fake_config_dir.mkdir()
fake_diaries_root.mkdir()
with patch.object(DirectoryManager, 'get_database_path', return_value=fake_db_path), \
patch.object(DirectoryManager, 'get_config_directory', return_value=fake_config_dir), \
patch.object(DirectoryManager, 'get_diaries_root', return_value=fake_diaries_root):
engine = create_engine(f"sqlite:///{fake_db_path}")
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
diary = TravelDiary(name="Viagem de Teste", directory_name="viagem_de_teste")
session.add(diary)
session.commit()
photo_file_path_str = str(fake_diaries_root / "viagem_de_teste" / "images" / "foto1.jpg")
photo = Photo(filepath=photo_file_path_str, name="Foto 1", photo_hash="hash123", fk_travel_diary_id=diary.id)
session.add(photo)
session.commit()
photo_file_path = Path(photo_file_path_str)
photo_file_path.parent.mkdir(parents=True)
photo_file_path.touch()
yield {
"session": session,
"db_path": fake_db_path,
"config_dir": fake_config_dir,
"diaries_root": fake_diaries_root,
}
session.close()
+39
View File
@@ -0,0 +1,39 @@
import zipfile
from pathlib import Path
from unittest.mock import patch, MagicMock
from pilgrim.service.backup_service import BackupService
from pilgrim.utils.directory_manager import DirectoryManager
import pytest
@patch.object(DirectoryManager, 'get_diaries_root')
@patch.object(DirectoryManager, 'get_config_directory')
@patch.object(DirectoryManager, 'get_database_path')
def test_create_backup_success(mock_get_db_path, mock_get_config_dir, mock_get_diaries_root, backup_test_env_files_only):
env = backup_test_env_files_only
session = env["session"]
mock_get_db_path.return_value = env["db_path"]
mock_get_config_dir.return_value = env["config_dir"]
mock_get_diaries_root.return_value = env["diaries_root"]
service = BackupService(session)
backup_zip_path = env["config_dir"] / "backup.zip"
success, returned_path = service.create_backup()
assert success is True
assert returned_path == backup_zip_path
assert backup_zip_path.exists()
with zipfile.ZipFile(backup_zip_path, 'r') as zf:
file_list = zf.namelist()
assert "database.sql" in file_list
assert "diaries/viagem_de_teste/images/foto1.jpg" in file_list
sql_dump = zf.read("database.sql").decode('utf-8')
assert "Viagem de Teste" in sql_dump
@patch.object(DirectoryManager, 'get_database_path')
def test_create_backup_fails_if_db_not_found(mock_get_db_path, tmp_path: Path):
non_existent_db_path = tmp_path / "non_existent.db"
mock_get_db_path.return_value = non_existent_db_path
mock_session = MagicMock()
service = BackupService(mock_session)
with pytest.raises(FileNotFoundError, match="No Database Found"):
service.create_backup()