mirror of https://github.com/gmbrax/Pilgrim.git
				
				
				
			Compare commits
	
		
			11 Commits
		
	
	
		
			b629741a54
			...
			e7ab84f77c
		
	
	| Author | SHA1 | Date | 
|---|---|---|
|  | e7ab84f77c | |
|  | fad21863c7 | |
|  | 9a5d112a26 | |
|  | 4af2a47606 | |
|  | 3d926993e8 | |
|  | ed55d33bc6 | |
|  | 819a2c7b6b | |
|  | 53e8b36a42 | |
|  | f825236c45 | |
|  | 8f36e5a770 | |
|  | 11e9cf6e75 | 
|  | @ -1,10 +1,18 @@ | ||||||
|  | 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 | ||||||
|  | from datetime import datetime | ||||||
| 
 | 
 | ||||||
|  | from pilgrim.models.entry import Entry | ||||||
| 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.entry import Entry | ||||||
| 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 +70,70 @@ 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() | ||||||
|  | 
 | ||||||
|  | @pytest.fixture | ||||||
|  | def entry_with_photo_references(session_with_one_diary): | ||||||
|  |     session, diary = session_with_one_diary | ||||||
|  |     photo1 = Photo(filepath="p1.jpg", name="P1", photo_hash="aaaaaaaa", fk_travel_diary_id=diary.id) | ||||||
|  |     photo2 = Photo(filepath="p2.jpg", name="P2", photo_hash="bbbbbbbb", fk_travel_diary_id=diary.id) | ||||||
|  |     session.add_all([photo1, photo2]) | ||||||
|  |     session.flush() | ||||||
|  |     entry = Entry( | ||||||
|  |         title="Entrada com Fotos", | ||||||
|  |         text="Texto com a foto A [[photo::aaaaaaaa]] e também a foto B [[photo::bbbbbbbb]].", | ||||||
|  |         date=datetime.now(), | ||||||
|  |         travel_diary_id=diary.id, | ||||||
|  |         photos=[photo1, photo2] | ||||||
|  |     ) | ||||||
|  |     session.add(entry) | ||||||
|  |     session.commit() | ||||||
|  |     session.refresh(entry) | ||||||
|  | 
 | ||||||
|  |     return session, entry | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @pytest.fixture | ||||||
|  | def session_with_multiple_entries(session_with_one_diary): | ||||||
|  |     session, diary = session_with_one_diary | ||||||
|  |     session.query(Entry).delete() | ||||||
|  |     entry1 = Entry(title="Entrada 1", text="Texto 1", date=datetime.now(), travel_diary_id=diary.id) | ||||||
|  |     entry2 = Entry(title="Entrada 2", text="Texto 2", date=datetime.now(), travel_diary_id=diary.id) | ||||||
|  | 
 | ||||||
|  |     session.add_all([entry1, entry2]) | ||||||
|  |     session.commit() | ||||||
|  | 
 | ||||||
|  |     return session, diary | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | @ -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() | ||||||
|  | @ -261,3 +261,46 @@ def test_delete_returns_none_if_entry_does_not_exist(db_session): | ||||||
|     non_existent_entry.id = 999 |     non_existent_entry.id = 999 | ||||||
|     result = service.delete(non_existent_entry) |     result = service.delete(non_existent_entry) | ||||||
|     assert result is None |     assert result is None | ||||||
|  | 
 | ||||||
|  | def test_delete_references_for_specific_photo(entry_with_photo_references): | ||||||
|  |     session, entry = entry_with_photo_references | ||||||
|  |     service = EntryService(session) | ||||||
|  |     updated_entry = service.delete_references_for_specific_photo(entry, "aaaaaaaa") | ||||||
|  |     assert "[[photo::aaaaaaaa]]" not in updated_entry.text | ||||||
|  |     assert "[[photo::bbbbbbbb]]" in updated_entry.text | ||||||
|  | 
 | ||||||
|  | def test_delete_specific_photo_reference_does_nothing_if_no_match(entry_with_photo_references): | ||||||
|  |     session, entry = entry_with_photo_references | ||||||
|  |     service = EntryService(session) | ||||||
|  | 
 | ||||||
|  |     original_text = entry.text | ||||||
|  |     updated_entry = service.delete_references_for_specific_photo(entry, "cccccccc") | ||||||
|  |     assert updated_entry.text == original_text | ||||||
|  | 
 | ||||||
|  | def test_delete_all_photo_references_removes_all_refs(entry_with_photo_references): | ||||||
|  |     session, entry = entry_with_photo_references | ||||||
|  |     service = EntryService(session) | ||||||
|  |     updated_entry = service.delete_all_photo_references(entry) | ||||||
|  |     assert "[[photo::aaaaaaaa]]" not in updated_entry.text | ||||||
|  |     assert "[[photo::bbbbbbbb]]" not in updated_entry.text | ||||||
|  | 
 | ||||||
|  | def test_delete_all_photo_references_uses_truncated_hash(session_with_one_diary): | ||||||
|  |     session, diary = session_with_one_diary | ||||||
|  |     service = EntryService(session) | ||||||
|  |     long_hash_photo = Photo( | ||||||
|  |         filepath="long.jpg", name="Long", | ||||||
|  |         photo_hash="1234567890abcdef",  # Hash com 16 caracteres | ||||||
|  |         fk_travel_diary_id=diary.id | ||||||
|  |     ) | ||||||
|  |     entry = Entry( | ||||||
|  |         title="Teste de Hash Curto", | ||||||
|  |         text="Referência com hash truncado [[photo::12345678]].",  # Texto usa só os 8 primeiros | ||||||
|  |         date=datetime.now(), | ||||||
|  |         travel_diary_id=diary.id | ||||||
|  |     ) | ||||||
|  |     entry.photos.append(long_hash_photo) | ||||||
|  |     session.add_all([long_hash_photo, entry]) | ||||||
|  |     session.commit() | ||||||
|  |     updated_entry = service.delete_all_photo_references(entry) | ||||||
|  |     expected_text = "Referência com hash truncado                   ." | ||||||
|  |     assert "[[photo::12345678]]" not in updated_entry.text | ||||||
|  |  | ||||||
|  | @ -1,9 +1,12 @@ | ||||||
| from unittest.mock import patch, MagicMock |  | ||||||
| from pathlib import Path | from pathlib import Path | ||||||
|  | from unittest.mock import patch, MagicMock | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| import pytest | import pytest | ||||||
| 
 | 
 | ||||||
| from pilgrim import TravelDiary | from pilgrim.models.photo import Photo | ||||||
|  | from pilgrim.models.travel_diary import TravelDiary | ||||||
|  | from pilgrim.models.entry import Entry | ||||||
| from pilgrim.service.travel_diary_service import TravelDiaryService | from pilgrim.service.travel_diary_service import TravelDiaryService | ||||||
| 
 | 
 | ||||||
| @patch.object(TravelDiaryService, '_ensure_diary_directory') | @patch.object(TravelDiaryService, '_ensure_diary_directory') | ||||||
|  | @ -141,3 +144,33 @@ def test_sanitize_directory_name_handles_uniqueness(db_session): | ||||||
| 
 | 
 | ||||||
|     third_sanitized_name = service._sanitize_directory_name("Viagem para a Praia") |     third_sanitized_name = service._sanitize_directory_name("Viagem para a Praia") | ||||||
|     assert third_sanitized_name == "viagem_para_a_praia_2" |     assert third_sanitized_name == "viagem_para_a_praia_2" | ||||||
|  | 
 | ||||||
|  | def test_delete_all_entries_successfully(session_with_multiple_entries): | ||||||
|  |     session, diary = session_with_multiple_entries | ||||||
|  |     service = TravelDiaryService(session) | ||||||
|  |     diary_id = 1 | ||||||
|  |     assert session.query(Entry).filter_by(fk_travel_diary_id=diary_id).count() == 2 | ||||||
|  |     result = service.delete_all_entries(diary) | ||||||
|  |     assert result is True | ||||||
|  |     assert session.query(Entry).filter_by(fk_travel_diary_id=diary_id).count() == 0 | ||||||
|  | 
 | ||||||
|  | @patch.object(TravelDiaryService, '_ensure_diary_directory') | ||||||
|  | @patch('pathlib.Path.unlink') | ||||||
|  | @patch('pathlib.Path.exists', return_value=True) | ||||||
|  | @patch('pilgrim.utils.DirectoryManager.get_diaries_root', return_value=Path("/fake/diaries_root")) | ||||||
|  | def test_delete_all_photos_orchestration( | ||||||
|  |     mock_ensure_dir, mock_unlink, mock_exists, mock_get_root, entry_with_photo_references | ||||||
|  | ): | ||||||
|  |     session, entry = entry_with_photo_references | ||||||
|  |     diary_id = entry.fk_travel_diary_id | ||||||
|  |     service = TravelDiaryService(session) | ||||||
|  |     assert session.query(Photo).filter_by(fk_travel_diary_id=diary_id).count() == 2 | ||||||
|  |     assert "[[photo::" in entry.text | ||||||
|  |     diary = session.get(TravelDiary, diary_id) | ||||||
|  |     result = service.delete_all_photos(diary) | ||||||
|  |     assert result is True | ||||||
|  |     photos_after_delete = session.query(Photo).filter_by(fk_travel_diary_id=diary_id).all() | ||||||
|  |     assert len(photos_after_delete) == 0 | ||||||
|  |     session.refresh(entry) | ||||||
|  |     assert "[[photo::" not in entry.text | ||||||
|  |     assert mock_unlink.call_count == 2 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue