Compare commits

...
32 Commits
Author SHA1 Message Date
Gustavo Henrique Santos Souza de Miranda cc95ce669f Merge remote-tracking branch 'origin/test/entryservice-unit-test' into test/entryservice-unit-test
# Conflicts:
#	tests/service/test_entry_service.py
2025-07-20 23:16:48 -03:00
Gustavo Henrique Santos Souza de Miranda d36ff829db Remove the shared fixtures that are available on conftest.py 2025-07-20 23:15:08 -03:00
Gustavo Henrique Santos Souza de Miranda 0173465943 Add all tests to test the delete of entries 2025-07-20 23:13:46 -03:00
Gustavo Henrique Santos Souza de Miranda 5b9a5bfe24 Add all tests to test the read of entries 2025-07-20 23:13:46 -03:00
Gustavo Henrique Santos Souza de Miranda 95a3a13ee2 Add all tests to test the update of entries 2025-07-20 23:13:46 -03:00
Gustavo Henrique Santos Souza de Miranda f9fb660d7c Add a test to test the creation of entries with null on nullable fields 2025-07-20 23:13:45 -03:00
Gustavo Henrique Santos Souza de Miranda f7a7289b5e 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 23:13:45 -03:00
Gustavo Henrique Santos Souza de Miranda 0227879bb3 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 23:13:45 -03:00
Gustavo Henrique Santos Souza de Miranda e46f02cc39 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 23:13:45 -03:00
Gustavo Henrique Miranda e9162ab25c Merge pull request #63 from gmbrax/refactor/shared-test-fixtures
Refactor to add conftest.py to share fixtures
2025-07-20 23:12:32 -03:00
Gustavo Henrique Santos Souza de Miranda 88a0b9cf80 Refactor to add conftest.py to share fixtures 2025-07-20 23:07:04 -03:00
Gustavo Henrique Santos Souza de Miranda 1629b9d52c Add all tests to test the delete of entries 2025-07-20 22:38:55 -03:00
Gustavo Henrique Santos Souza de Miranda 790a9ea3f0 Add all tests to test the read of entries 2025-07-20 22:26:40 -03:00
Gustavo Henrique Santos Souza de Miranda cec1827635 Add all tests to test the update of entries 2025-07-20 22:12:09 -03:00
Gustavo Henrique Santos Souza de Miranda 1c8026620c Add a test to test the creation of entries with null on nullable fields 2025-07-20 20:47:12 -03:00
Gustavo Henrique Santos Souza de Miranda fcbf465c43 Merge branch 'staging' into test/entryservice-unit-test 2025-07-20 18:08:11 -03:00
Gustavo Henrique Miranda 4dda85d8a3 Merge pull request #62 from gmbrax/fix/model-entry-nullable-fields
fix the entry model to not allow the title nor the date to be null
2025-07-20 17:53:27 -03:00
Gustavo Henrique Santos Souza de Miranda 5a28afc540 fix the entry model to not allow the title nor the date to be null 2025-07-20 17:34:57 -03:00
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
Gustavo Henrique Miranda 78e45e26fd Update pylint_sonarqube.yml
Fix the ruff error on the sonarcloud scan
2025-07-19 19:06:53 -03:00
Gustavo Henrique Miranda cc68bbcf2e Update pylint_sonarqube.yml
Add the missing parameters for SonarQube
2025-07-19 18:56:19 -03:00
Gustavo Henrique Miranda 9a698596b1 Update and rename pylint.yml to pylint_sonarqube.yml
Add RUFF and SonarQube scanning
2025-07-19 18:52:53 -03:00
Gustavo Henrique Miranda 0cbcbd3a8d Update CHANGELOG.md
Revert the markdown format missing from the last update
2025-07-19 17:40:01 -03:00
Gustavo Henrique Miranda a1e718c1fc Update CHANGELOG.md
Added info for the next alpha version 0.0.4
2025-07-19 17:34:05 -03:00
Gustavo Henrique Miranda 8919e158bc Merge pull request #60 from gmbrax/fix/Importing-duplicate-images
Fix the bug that collides the hash if identical images
2025-07-19 03:23:54 -03:00
13 changed files with 450 additions and 99 deletions
-24
View File
@@ -1,24 +0,0 @@
name: Pylint
on: [push]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10"]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
pip install pylint
- name: Analysing the code with pylint
run: |
pylint --disable=C0114,C0115,C0116 --exit-zero $(git ls-files '*.py')
+63
View File
@@ -0,0 +1,63 @@
name: Pylint and SonarCloud
on:
push:
branches: [ main, master, staging ]
pull_request:
branches: [ main, master, staging ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10"]
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Necessário para SonarCloud
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
pip install pylint ruff coverage pytest
- name: Analysing the code with pylint (console output)
run: |
pylint --disable=C0114,C0115,C0116 --exit-zero $(git ls-files '*.py') || true
- name: Generate Pylint report for SonarCloud
run: |
pylint --disable=C0114,C0115,C0116 --output-format=json --exit-zero $(git ls-files '*.py') > pylint-report.json || true
- name: Run Ruff
run: |
ruff check --output-format=json . > ruff-report.json || true
- name: Run tests with coverage (if you have tests)
run: |
if [ -d "tests" ] || [ -f "test_*.py" ] || [ -f "*_test.py" ]; then
coverage run -m pytest || true
coverage xml || true
else
echo "No tests found, skipping coverage"
fi
- name: SonarCloud Scan
uses: SonarSource/sonarqube-scan-action@v5.0.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
with:
args: >
-Dsonar.projectKey=gmbrax_Pilgrim
-Dsonar.organization=gmbrax
-Dsonar.python.pylint.reportPaths=pylint-report.json
-Dsonar.python.ruff.reportPaths=ruff-report.json
-Dsonar.python.coverage.reportPaths=coverage.xml
+47 -30
View File
@@ -1,51 +1,68 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
## [Unreleased]
## Planned
* Installation Method 1 (repository compilation)
* Organization of trips by date, location, or theme
* Enhanced photo management features
* Search functionality
* Export features
* Testing implementation
### Planned
## [0.0.4] - 2025-07-19
- Installation Method 1 (repository compilation)
- Organization of trips by date, location, or theme
- Enhanced photo management features
- Search functionality
- Export features
- Testing implementation
### Added
* 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
* Automatic diary list refresh when returning to the diary screen
* Application configuration management with a new centralized config system
* Database location and initialization now configurable via the new config manager
* Automatic migration of database file to the configuration directory
* Display of database URL on application startup for transparency
* Duplicate photo detection before photo creation to prevent redundant entries
* Photo hash indexing to improve photo lookup performance
### Changed
* Enhanced feedback and validation when editing or creating diary names
* Streamlined and unified save logic for diary modals, reducing duplicated behavior
* 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 layout and scrolling behavior improved for better usability
* Photo hash generation now relies on existing service-provided hashes instead of local computation
### Improved
* Enhanced feedback and validation when editing or creating diary names
* Streamlined and unified save logic for diary modals, reducing duplicated behavior
* Sidebar layout and scrolling behavior for better usability
## [0.0.3] - 2025-07-07
### 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
### Changed
- Changed the license in pyproject.toml to BSD
* Changed the license in pyproject.toml to BSD
## [0.0.1] - 2025-07-06
### Added
- Initial alpha release of Pilgrim travel diary application
- Create and edit travel diaries
- Create and edit diary entries
- Photo ingestion system
- Photo addition and reference via sidebar
- Text User Interface (TUI) built with Textual framework
- Pre-compiled binary installation method (Method 2)
- Support for Linux operating systems
- Basic project documentation (README)
* Initial alpha release of Pilgrim travel diary application
* Create and edit travel diaries
* Create and edit diary entries
* Photo ingestion system
* Photo addition and reference via sidebar
* Text User Interface (TUI) built with Textual framework
* Pre-compiled binary installation method (Method 2)
* Support for Linux operating systems
* Basic project documentation (README)
### Known Issues
- Installation Method 1 not yet implemented
- No testing suite implemented yet
- Some features may be unstable in an alpha version
[Unreleased]: https://github.com/username/pilgrim/compare/v0.0.1...HEAD
[0.0.1]: https://github.com/username/pilgrim/releases/tag/v0.0.1
* Installation Method 1 not yet implemented
* No testing suite implemented yet
* Some features may be unstable in an alpha version
+28 -33
View File
@@ -1,36 +1,31 @@
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[build-system]
requires = ["hatchling"]
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]
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.urls]
Homepage = "https://github.com/gmbrax/Pilgrim/"
Issues = "https://github.com/gmbrax/Pilgrim/issues"
]
[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"
[project.scripts]
pilgrim = "pilgrim.command:main"
+1 -1
View File
@@ -1,5 +1,5 @@
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import declarative_base
from sqlalchemy.orm import sessionmaker
from pathlib import Path
import os
+4 -3
View File
@@ -4,15 +4,16 @@ from pilgrim.models.photo_in_entry import photo_entry_association
from sqlalchemy import Column, Integer, String, ForeignKey, DateTime
from sqlalchemy.orm import relationship
from ..database import Base
from pilgrim.database import Base
class Entry(Base):
__tablename__ = "entries"
id = Column(Integer, primary_key=True)
title = Column(String)
title = Column(String,nullable=False)
text = Column(String)
date = Column(DateTime)
date = Column(DateTime,nullable=False)
photos = relationship(
"Photo",
secondary=photo_entry_association,
+2 -1
View File
@@ -7,7 +7,8 @@ from sqlalchemy.orm import relationship
from sqlalchemy.sql.schema import Index
from pilgrim.models.photo_in_entry import photo_entry_association
from ..database import Base
from pilgrim.database import Base
class Photo(Base):
+1 -1
View File
@@ -1,6 +1,6 @@
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,
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.orm import relationship
from .. import database
from pilgrim.database import Base
class TravelDiary(database.Base):
class TravelDiary(Base):
__tablename__ = "travel_diaries"
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False)
+3 -3
View File
@@ -1,9 +1,9 @@
from datetime import datetime
from typing import List
from ..models.entry import Entry
from ..models.travel_diary import TravelDiary
from ..models.photo import Photo # ✨ Importe o modelo Photo
from pilgrim.models.entry import Entry
from pilgrim.models.travel_diary import TravelDiary
from pilgrim.models.photo import Photo # ✨ Importe o modelo Photo
class EntryService:
+1 -1
View File
@@ -6,7 +6,7 @@ from pathlib import Path
from pilgrim.utils import DirectoryManager
from sqlalchemy.exc import IntegrityError
from ..models.travel_diary import TravelDiary
from pilgrim.models.travel_diary import TravelDiary
class TravelDiaryService:
+28
View File
@@ -0,0 +1,28 @@
import pytest
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from pilgrim.database import Base
from pilgrim.models.travel_diary import TravelDiary
# Todos os imports necessários para as fixtures devem estar aqui
# ...
@pytest.fixture(scope="function")
def db_session():
"""Esta fixture agora está disponível para TODOS os testes."""
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):
"""Esta também fica disponível para todos."""
travel_diary = TravelDiary(name="My Travel Diary", directory_name="viagem-teste")
db_session.add(travel_diary)
db_session.commit()
return db_session
+269
View File
@@ -0,0 +1,269 @@
from re import search
import pytest
from datetime import datetime
from unittest.mock import Mock
from sqlalchemy import create_engine
from sqlalchemy.exc import IntegrityError
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
def session_with_an_entry(populated_db_session):
session = populated_db_session
initial_entry = Entry(
title="Título Original",
text="Texto original.",
date=datetime(2025, 1, 1),
travel_diary_id=1
)
session.add(initial_entry)
session.commit()
return session, initial_entry.id
@pytest.fixture
def session_with_multiple_entries(populated_db_session):
"""Fixture que cria um diário e duas entradas para ele."""
session = populated_db_session
entry1 = Entry(title="Entrada 1", text="Texto 1", date=datetime(2025, 1, 1), travel_diary_id=1)
entry2 = Entry(title="Entrada 2", text="Texto 2", date=datetime(2025, 1, 2), travel_diary_id=1)
session.add_all([entry1, entry2])
session.commit()
return 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"
def test_create_entry_fails_with_null_title(populated_db_session):
session = populated_db_session
service = EntryService(session)
diary_id = 1
with pytest.raises(IntegrityError):
service.create(
travel_diary_id=diary_id,
title=None,
text="Um texto qualquer.",
date=datetime.now(),
photos=[]
)
def test_create_entry_fails_with_null_date(populated_db_session):
session = populated_db_session
service = EntryService(session)
diary_id = 1
with pytest.raises(IntegrityError):
service.create(
travel_diary_id=diary_id,
title="Sabado de sol",
text="Um texto qualquer.",
date=None,
photos=[]
)
def test_create_entry_fails_with_null_diary_id(populated_db_session):
session = populated_db_session
service = EntryService(session)
diary_id = 1
result = service.create(
travel_diary_id=None,
title="Sabado de sol",
text="Um texto qualquer.",
date=datetime.now(),
photos=[]
)
assert result is None
def test_ready_by_id_successfully(session_with_an_entry):
session,_ = session_with_an_entry
service = EntryService(session)
search_id = 1
result = service.read_by_id(search_id)
assert result is not None
def test_ready_by_id_fails_when_id_is_invalid(db_session):
session = db_session
service = EntryService(session)
invalid_id = 666
result = service.read_by_id(invalid_id)
assert result is None
def test_read_all_returns_all_entries(session_with_multiple_entries):
session = session_with_multiple_entries
service = EntryService(session)
all_entries = service.read_all()
assert isinstance(all_entries, list)
assert len(all_entries) == 2
assert all_entries[0].title == "Entrada 1"
assert all_entries[1].title == "Entrada 2"
def test_read_all_returns_empty_list_on_empty_db(db_session):
session = db_session
service = EntryService(session)
all_entries = service.read_all()
assert isinstance(all_entries, list)
assert len(all_entries) == 0
def test_update_entry_successfully(session_with_an_entry):
session, entry_id = session_with_an_entry
service = EntryService(session)
entry_src = session.query(Entry).filter_by(id=entry_id).one()
new_date = datetime(2025, 1, 2)
entry_dst = Entry(
title="Título Atualizado",
text="Texto atualizado.",
date=new_date,
travel_diary_id=1, # Mantemos o mesmo travel_diary_id
photos=[]
)
updated_entry = service.update(entry_src, entry_dst)
assert updated_entry is not None
assert updated_entry.id == entry_id
assert updated_entry.title == "Título Atualizado"
assert updated_entry.text == "Texto atualizado."
entry_in_db = session.query(Entry).filter_by(id=entry_id).one()
assert entry_in_db.title == "Título Atualizado"
def test_update_entry_fails_if_entry_does_not_exist(db_session):
service = EntryService(db_session)
non_existent_entry = Entry(
title="dummy",
text="dummy",
date=datetime.now(),
travel_diary_id=1)
non_existent_entry.id = 999
entry_with_new_data = Entry(title="Novo Título", text="Novo Texto", date=datetime.now(), travel_diary_id=1)
result = service.update(non_existent_entry, entry_with_new_data)
assert result is None
def test_update_fails_with_null_title(session_with_an_entry):
session, entry_id = session_with_an_entry
service = EntryService(session)
entry_src = session.query(Entry).filter_by(id=entry_id).one()
entry_dst = Entry(
title=None,
text="Texto atualizado.",
date=datetime.now(),
travel_diary_id=1,
photos=[]
)
with pytest.raises(IntegrityError):
service.update(entry_src, entry_dst)
def test_update_fails_with_null_date(session_with_an_entry):
session, entry_id = session_with_an_entry
service = EntryService(session)
entry_src = session.query(Entry).filter_by(id=entry_id).one()
entry_dst = Entry(
title=entry_src.title,
text="Texto atualizado.",
date=None,
travel_diary_id=1,
photos=[]
)
with pytest.raises(IntegrityError):
service.update(entry_src, entry_dst)
def test_update_fails_with_null_diary_id(session_with_an_entry):
session, entry_id = session_with_an_entry
service = EntryService(session)
entry_src = session.query(Entry).filter_by(id=entry_id).one()
entry_dst = Entry(
title=entry_src.title,
text="Texto atualizado.",
date=datetime.now(),
travel_diary_id=None,
photos=[]
)
with pytest.raises(IntegrityError):
service.update(entry_src, entry_dst)
def test_delete_successfully_removes_entry(session_with_an_entry):
session, entry_id = session_with_an_entry
service = EntryService(session)
entry_to_delete = service.read_by_id(entry_id)
assert entry_to_delete is not None
deleted_entry = service.delete(entry_to_delete)
assert deleted_entry is not None
assert deleted_entry.id == entry_id
entry_in_db = service.read_by_id(entry_id)
assert entry_in_db is None
def test_delete_returns_none_if_entry_does_not_exist(db_session):
service = EntryService(db_session)
non_existent_entry = Entry(
title="dummy",
text="dummy",
date=datetime.now(),
travel_diary_id=1)
non_existent_entry.id = 999
result = service.delete(non_existent_entry)
assert result is None