Skip to content

Added unit tests for client & API#2

Merged
spuerta10 merged 23 commits into
mainfrom
feat/unit-tests
Oct 16, 2025
Merged

Added unit tests for client & API#2
spuerta10 merged 23 commits into
mainfrom
feat/unit-tests

Conversation

@spuerta10
Copy link
Copy Markdown
Owner

@spuerta10 spuerta10 commented Oct 16, 2025

Summary by Sourcery

Introduce a comprehensive unit test suite for client and API components, refine module imports and Docker Compose configuration, and enhance CI pipeline and development dependencies to support testing

Enhancements:

  • Refactor module imports to use explicit register_ticket_api namespace
  • Validate empty seed input in TOTPGenerator and exclude main block from coverage
  • Update Docker Compose to use environment variable syntax for database credentials

Build:

  • Add testing and development dependencies (pytest, pytest-asyncio, pytest-cov, pre-commit, coverage, and related packages)

CI:

  • Update GitHub Actions workflow to install dependencies and run unit tests with coverage report

Documentation:

  • Add pytest.ini for test configuration and discovery

Tests:

  • Add unit tests for TicketService, UserService, UserRepository, TicketRepository, and TOTPGenerator covering success and failure scenarios

@spuerta10 spuerta10 self-assigned this Oct 16, 2025
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Oct 16, 2025

Reviewer's Guide

This PR introduces comprehensive unit tests for the client and API layers, refactors module imports to a namespaced structure, updates project dependencies and CI configuration to support testing, enhances input validation in TOTPGenerator, and refines environment variable usage in Docker Compose.

Class diagram for updated TOTPGenerator input validation

classDiagram
    class TOTPGenerator {
        +TOTP_INTERVAL_SECONDS: int
        +__init__(seed_base64: str)
        +generate_code() str
    }
    TOTPGenerator : __totp
    TOTPGenerator : "raises ValueError if seed_base64 is empty"
Loading

Class diagram for namespaced module imports in API

classDiagram
    class TicketsController {
    }
    class UserRepository {
    }
    class TicketRepository {
    }
    class TicketService {
    }
    class PostgreSQLDbContext {
    }
    TicketsController <.. TicketService
    TicketService <.. TicketRepository
    TicketService <.. UserRepository
    TicketRepository <.. PostgreSQLDbContext
    UserRepository <.. PostgreSQLDbContext
Loading

File-Level Changes

Change Details Files
Add test dependencies and CI configuration
  • Added pytest, pytest-asyncio, pytest-cov, coverage, pre-commit, and related packages to requirements.txt
  • Created pytest.ini with test discovery settings and asyncio_mode
  • Updated GitHub Actions static-code-analysis workflow to install dependencies before running tests
requirements.txt
.github/workflows/static-code-analysis.yml
pytest.ini
Restructure imports to use namespaced package
  • Prefixed all internal imports with register_ticket_api across modules
  • Adjusted init.py files in controllers, services, repositories, interfaces, entities, and exceptions
  • Updated main.py to import from register_ticket_api subpackages
src/register_ticket_api/controllers/tickets_controller.py
src/register_ticket_api/controllers/users_controller.py
src/register_ticket_api/controllers/__init__.py
src/register_ticket_api/services/ticket_service.py
src/register_ticket_api/services/__init__.py
src/register_ticket_api/repositories/__init__.py
src/register_ticket_api/interfaces/__init__.py
src/register_ticket_api/interfaces/i_ticket_repository.py
src/register_ticket_api/interfaces/i_user_repository.py
src/register_ticket_api/entities/__init__.py
src/register_ticket_api/exceptions/__init__.py
src/register_ticket_api/infraestructure/__init__.py
src/register_ticket_api/main.py
Enhance TOTPGenerator validation and coverage exclusion
  • Added check to raise ValueError when seed_base64 is empty
  • Marked main block with '# pragma: no cover' to exclude from coverage
src/client/totp_generator.py
Refine Docker Compose environment variable usage
  • Replaced placeholder braces with ${DB_USER}, ${DB_PASSWORD}, and ${DB_NAME}
  • Added invocation hint comment at top of docker-compose.yml
docker/docker-compose.yml
Add comprehensive unit tests for services, repositories, and client
  • Implemented service tests for register_ticket and log_attendance flows in TicketService
  • Created repository tests for UserRepository and TicketRepository with AsyncMock
  • Added TOTPGenerator tests covering initialization, invalid input, and time-based code changes
  • Configured fixtures for sample entities and mocked dependencies
tests/unit/client/test_totp_generator.py
tests/unit/register_ticket_api/services/test_ticket_service.py
tests/unit/register_ticket_api/repositories/test_user_repository.py
tests/unit/register_ticket_api/repositories/test_ticket_repository.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes - here's some feedback:

  • The tests import from src.register_ticket_api but pytest.ini sets pythonpath=src, so you should either update the imports to register_ticket_api.* or adjust pytest.ini to include the src package prefix to ensure modules resolve correctly.
  • The test_ticket_service file exceeds 350 lines and covers multiple scenarios—consider splitting it into smaller modules (e.g. one for register_ticket and one for log_attendance) to improve readability and maintainability.
  • The mark_ticket_as_used signature currently returns Any with a comment ‘# bool’; updating the return type annotation to bool (and removing the Any) will make the API clearer and more type-safe.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The tests import from src.register_ticket_api but pytest.ini sets pythonpath=src, so you should either update the imports to register_ticket_api.* or adjust pytest.ini to include the `src` package prefix to ensure modules resolve correctly.
- The test_ticket_service file exceeds 350 lines and covers multiple scenarios—consider splitting it into smaller modules (e.g. one for register_ticket and one for log_attendance) to improve readability and maintainability.
- The mark_ticket_as_used signature currently returns Any with a comment ‘# bool’; updating the return type annotation to bool (and removing the Any) will make the API clearer and more type-safe.

## Individual Comments

### Comment 1
<location> `src/register_ticket_api/repositories/ticket_repository.py:56` </location>
<code_context>
             return Ticket(**row)
         return None

-    async def mark_ticket_as_used(self, ticket_id: UUID) -> Any[bool]:
+    async def mark_ticket_as_used(self, ticket_id: UUID) -> Any:  # bool
         FN_NAME: str = "fn_mark_ticket_as_used"
         try:
</code_context>

<issue_to_address>
**suggestion:** Return type annotation is now less specific; consider restoring type clarity.

If the function always returns a boolean, please annotate the return type as 'bool' for better maintainability and static analysis.

```suggestion
    async def mark_ticket_as_used(self, ticket_id: UUID) -> bool:
```
</issue_to_address>

### Comment 2
<location> `tests/unit/register_ticket_api/services/test_ticket_service.py:339-340` </location>
<code_context>
+        )
+
+
+async def test_log_attendance_db_operation_exception(
+    ticket_service: TicketService,
+    mock_ticket_repo: AsyncMock,
+    sample_registered_ticket: Ticket,
+    sample_attendance_log: AttendanceLog,
+) -> None:
+    """Test attendance logging handles database operation errors."""
+    with patch("src.register_ticket_api.services.ticket_service.pyotp.TOTP") as mock_totp_class:
+        mock_totp_instance = MagicMock()
+        mock_totp_instance.verify.return_value = True
+        mock_totp_class.return_value = mock_totp_instance
+
+        mock_ticket_repo.get_by_ticket_details.return_value = sample_registered_ticket
+        mock_ticket_repo.mark_ticket_as_used.side_effect = DbOperationException("DB Error")
+
+        with pytest.raises(AppValidationException, match="Error creating user"):
+            await ticket_service.log_attendance(sample_attendance_log)
+
</code_context>

<issue_to_address>
**suggestion (testing):** Error message in assertion may be misleading for attendance logging.

Please ensure the test checks for an error message relevant to attendance logging, not user creation, to accurately reflect the scenario being tested.

```suggestion
        with pytest.raises(AppValidationException, match="Error logging attendance"):
            await ticket_service.log_attendance(sample_attendance_log)
```
</issue_to_address>

### Comment 3
<location> `tests/unit/register_ticket_api/services/test_ticket_service.py:280-299` </location>
<code_context>
+        await ticket_service.log_attendance(sample_attendance_log)
+
+
+async def test_log_attendance_ticket_no_seed(
+    ticket_service: TicketService,
+    mock_ticket_repo: AsyncMock,
+    sample_attendance_log: AttendanceLog,
+) -> None:
+    """Test attendance logging fails when ticket has no seed."""
+    ticket_no_seed = Ticket(
+        id=uuid4(),
+        seat=TEST_SEAT,
+        gate=TEST_GATE,
+        user_id=uuid4(),
+        seed=None,
+        status="valid",
+        created_at="2024-01-01T00:00:00Z",
+        used_at=None,
+    )
+    mock_ticket_repo.get_by_ticket_details.return_value = ticket_no_seed
+
+    with pytest.raises(AppValidationException, match="Ticket has no seed"):
+        await ticket_service.log_attendance(sample_attendance_log)
+
</code_context>

<issue_to_address>
**suggestion (testing):** Edge case for empty string seed is not covered.

Please add a test for tickets where the seed is an empty string to ensure this scenario is handled correctly.

```suggestion
async def test_log_attendance_ticket_no_seed(
    ticket_service: TicketService,
    mock_ticket_repo: AsyncMock,
    sample_attendance_log: AttendanceLog,
) -> None:
    """Test attendance logging fails when ticket has no seed."""
    ticket_no_seed = Ticket(
        id=uuid4(),
        seat=TEST_SEAT,
        gate=TEST_GATE,
        user_id=uuid4(),
        seed=None,
        status="valid",
        created_at="2024-01-01T00:00:00Z",
        used_at=None,
    )
    mock_ticket_repo.get_by_ticket_details.return_value = ticket_no_seed

    with pytest.raises(AppValidationException, match="Ticket has no seed"):
        await ticket_service.log_attendance(sample_attendance_log)


async def test_log_attendance_ticket_empty_seed(
    ticket_service: TicketService,
    mock_ticket_repo: AsyncMock,
    sample_attendance_log: AttendanceLog,
) -> None:
    """Test attendance logging fails when ticket seed is an empty string."""
    ticket_empty_seed = Ticket(
        id=uuid4(),
        seat=TEST_SEAT,
        gate=TEST_GATE,
        user_id=uuid4(),
        seed="",
        status="valid",
        created_at="2024-01-01T00:00:00Z",
        used_at=None,
    )
    mock_ticket_repo.get_by_ticket_details.return_value = ticket_empty_seed

    with pytest.raises(AppValidationException, match="Ticket has no seed"):
        await ticket_service.log_attendance(sample_attendance_log)
```
</issue_to_address>

### Comment 4
<location> `tests/unit/register_ticket_api/repositories/test_ticket_repository.py:39-59` </location>
<code_context>
+    return TicketRepository(db_context=mock_db_context)
+
+
+async def test_register_ticket_calls_stored_procedure(
+    mock_db_context: AsyncMock,
+    sample_user: User,
+    sample_ticket: Ticket,
+    ticket_repository: TicketRepository,
+) -> None:
+    mock_conn = AsyncMock()
+    mock_conn.execute.return_value = 1  # emulates 1 affected row
+    mock_db_context.get_connection.return_value = mock_conn
+
+    result: bool = await ticket_repository.register_ticket(user=sample_user, ticket=sample_ticket)
+
+    mock_conn.execute.assert_awaited_once_with(
+        "CALL sp_register_ticket_to_user($1, $2)",
+        sample_ticket.id,
+        sample_user.id,
+    )
+    assert result is True
+
+
</code_context>

<issue_to_address>
**suggestion (testing):** Consider adding a test for register_ticket when the stored procedure fails.

Please add a test case for register_ticket that covers stored procedure failure scenarios, such as returning 0 affected rows or raising an exception, to verify proper error handling.

```suggestion
+
+async def test_register_ticket_calls_stored_procedure(
+    mock_db_context: AsyncMock,
+    sample_user: User,
+    sample_ticket: Ticket,
+    ticket_repository: TicketRepository,
+) -> None:
+    mock_conn = AsyncMock()
+    mock_conn.execute.return_value = 1  # emulates 1 affected row
+    mock_db_context.get_connection.return_value = mock_conn
+
+    result: bool = await ticket_repository.register_ticket(user=sample_user, ticket=sample_ticket)
+
+    mock_conn.execute.assert_awaited_once_with(
+        "CALL sp_register_ticket_to_user($1, $2)",
+        sample_ticket.id,
+        sample_user.id,
+    )
+    assert result is True
+
+
+# Test when stored procedure returns 0 affected rows (failure)
+async def test_register_ticket_returns_false_on_zero_rows(
+    mock_db_context: AsyncMock,
+    sample_user: User,
+    sample_ticket: Ticket,
+    ticket_repository: TicketRepository,
+) -> None:
+    mock_conn = AsyncMock()
+    mock_conn.execute.return_value = 0  # emulates 0 affected rows
+    mock_db_context.get_connection.return_value = mock_conn
+
+    result: bool = await ticket_repository.register_ticket(user=sample_user, ticket=sample_ticket)
+    assert result is False
+
+
+# Test when stored procedure raises an exception
+async def test_register_ticket_raises_on_db_exception(
+    mock_db_context: AsyncMock,
+    sample_user: User,
+    sample_ticket: Ticket,
+    ticket_repository: TicketRepository,
+) -> None:
+    mock_conn = AsyncMock()
+    mock_conn.execute.side_effect = Exception("DB error")
+    mock_db_context.get_connection.return_value = mock_conn
+
+    with pytest.raises(DbOperationException):
+        await ticket_repository.register_ticket(user=sample_user, ticket=sample_ticket)
+
```
</issue_to_address>

### Comment 5
<location> `tests/unit/register_ticket_api/repositories/test_ticket_repository.py:57` </location>
<code_context>
async def test_register_ticket_calls_stored_procedure(
    mock_db_context: AsyncMock,
    sample_user: User,
    sample_ticket: Ticket,
    ticket_repository: TicketRepository,
) -> None:
    mock_conn = AsyncMock()
    mock_conn.execute.return_value = 1  # emulates 1 affected row
    mock_db_context.get_connection.return_value = mock_conn

    result: bool = await ticket_repository.register_ticket(user=sample_user, ticket=sample_ticket)

    mock_conn.execute.assert_awaited_once_with(
        "CALL sp_register_ticket_to_user($1, $2)",
        sample_ticket.id,
        sample_user.id,
    )
    assert result is True

</code_context>

<issue_to_address>
**suggestion (code-quality):** Simplify comparison to boolean ([`simplify-boolean-comparison`](https://docs.sourcery.ai/Reference/Default-Rules/refactorings/simplify-boolean-comparison/))

```suggestion
    assert result
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

return Ticket(**row)
return None

async def mark_ticket_as_used(self, ticket_id: UUID) -> Any[bool]:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Return type annotation is now less specific; consider restoring type clarity.

If the function always returns a boolean, please annotate the return type as 'bool' for better maintainability and static analysis.

Suggested change
async def mark_ticket_as_used(self, ticket_id: UUID) -> Any[bool]:
async def mark_ticket_as_used(self, ticket_id: UUID) -> bool:

Comment on lines +339 to +340
with pytest.raises(AppValidationException, match="Error creating user"):
await ticket_service.log_attendance(sample_attendance_log)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Error message in assertion may be misleading for attendance logging.

Please ensure the test checks for an error message relevant to attendance logging, not user creation, to accurately reflect the scenario being tested.

Suggested change
with pytest.raises(AppValidationException, match="Error creating user"):
await ticket_service.log_attendance(sample_attendance_log)
with pytest.raises(AppValidationException, match="Error logging attendance"):
await ticket_service.log_attendance(sample_attendance_log)

Comment on lines +280 to +299
async def test_log_attendance_ticket_no_seed(
ticket_service: TicketService,
mock_ticket_repo: AsyncMock,
sample_attendance_log: AttendanceLog,
) -> None:
"""Test attendance logging fails when ticket has no seed."""
ticket_no_seed = Ticket(
id=uuid4(),
seat=TEST_SEAT,
gate=TEST_GATE,
user_id=uuid4(),
seed=None,
status="valid",
created_at="2024-01-01T00:00:00Z",
used_at=None,
)
mock_ticket_repo.get_by_ticket_details.return_value = ticket_no_seed

with pytest.raises(AppValidationException, match="Ticket has no seed"):
await ticket_service.log_attendance(sample_attendance_log)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Edge case for empty string seed is not covered.

Please add a test for tickets where the seed is an empty string to ensure this scenario is handled correctly.

Suggested change
async def test_log_attendance_ticket_no_seed(
ticket_service: TicketService,
mock_ticket_repo: AsyncMock,
sample_attendance_log: AttendanceLog,
) -> None:
"""Test attendance logging fails when ticket has no seed."""
ticket_no_seed = Ticket(
id=uuid4(),
seat=TEST_SEAT,
gate=TEST_GATE,
user_id=uuid4(),
seed=None,
status="valid",
created_at="2024-01-01T00:00:00Z",
used_at=None,
)
mock_ticket_repo.get_by_ticket_details.return_value = ticket_no_seed
with pytest.raises(AppValidationException, match="Ticket has no seed"):
await ticket_service.log_attendance(sample_attendance_log)
async def test_log_attendance_ticket_no_seed(
ticket_service: TicketService,
mock_ticket_repo: AsyncMock,
sample_attendance_log: AttendanceLog,
) -> None:
"""Test attendance logging fails when ticket has no seed."""
ticket_no_seed = Ticket(
id=uuid4(),
seat=TEST_SEAT,
gate=TEST_GATE,
user_id=uuid4(),
seed=None,
status="valid",
created_at="2024-01-01T00:00:00Z",
used_at=None,
)
mock_ticket_repo.get_by_ticket_details.return_value = ticket_no_seed
with pytest.raises(AppValidationException, match="Ticket has no seed"):
await ticket_service.log_attendance(sample_attendance_log)
async def test_log_attendance_ticket_empty_seed(
ticket_service: TicketService,
mock_ticket_repo: AsyncMock,
sample_attendance_log: AttendanceLog,
) -> None:
"""Test attendance logging fails when ticket seed is an empty string."""
ticket_empty_seed = Ticket(
id=uuid4(),
seat=TEST_SEAT,
gate=TEST_GATE,
user_id=uuid4(),
seed="",
status="valid",
created_at="2024-01-01T00:00:00Z",
used_at=None,
)
mock_ticket_repo.get_by_ticket_details.return_value = ticket_empty_seed
with pytest.raises(AppValidationException, match="Ticket has no seed"):
await ticket_service.log_attendance(sample_attendance_log)

Comment on lines +39 to +59

async def test_register_ticket_calls_stored_procedure(
mock_db_context: AsyncMock,
sample_user: User,
sample_ticket: Ticket,
ticket_repository: TicketRepository,
) -> None:
mock_conn = AsyncMock()
mock_conn.execute.return_value = 1 # emulates 1 affected row
mock_db_context.get_connection.return_value = mock_conn

result: bool = await ticket_repository.register_ticket(user=sample_user, ticket=sample_ticket)

mock_conn.execute.assert_awaited_once_with(
"CALL sp_register_ticket_to_user($1, $2)",
sample_ticket.id,
sample_user.id,
)
assert result is True


Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Consider adding a test for register_ticket when the stored procedure fails.

Please add a test case for register_ticket that covers stored procedure failure scenarios, such as returning 0 affected rows or raising an exception, to verify proper error handling.

Suggested change
async def test_register_ticket_calls_stored_procedure(
mock_db_context: AsyncMock,
sample_user: User,
sample_ticket: Ticket,
ticket_repository: TicketRepository,
) -> None:
mock_conn = AsyncMock()
mock_conn.execute.return_value = 1 # emulates 1 affected row
mock_db_context.get_connection.return_value = mock_conn
result: bool = await ticket_repository.register_ticket(user=sample_user, ticket=sample_ticket)
mock_conn.execute.assert_awaited_once_with(
"CALL sp_register_ticket_to_user($1, $2)",
sample_ticket.id,
sample_user.id,
)
assert result is True
+
+async def test_register_ticket_calls_stored_procedure(
+ mock_db_context: AsyncMock,
+ sample_user: User,
+ sample_ticket: Ticket,
+ ticket_repository: TicketRepository,
+) -> None:
+ mock_conn = AsyncMock()
+ mock_conn.execute.return_value = 1 # emulates 1 affected row
+ mock_db_context.get_connection.return_value = mock_conn
+
+ result: bool = await ticket_repository.register_ticket(user=sample_user, ticket=sample_ticket)
+
+ mock_conn.execute.assert_awaited_once_with(
+ "CALL sp_register_ticket_to_user($1, $2)",
+ sample_ticket.id,
+ sample_user.id,
+ )
+ assert result is True
+
+
+# Test when stored procedure returns 0 affected rows (failure)
+async def test_register_ticket_returns_false_on_zero_rows(
+ mock_db_context: AsyncMock,
+ sample_user: User,
+ sample_ticket: Ticket,
+ ticket_repository: TicketRepository,
+) -> None:
+ mock_conn = AsyncMock()
+ mock_conn.execute.return_value = 0 # emulates 0 affected rows
+ mock_db_context.get_connection.return_value = mock_conn
+
+ result: bool = await ticket_repository.register_ticket(user=sample_user, ticket=sample_ticket)
+ assert result is False
+
+
+# Test when stored procedure raises an exception
+async def test_register_ticket_raises_on_db_exception(
+ mock_db_context: AsyncMock,
+ sample_user: User,
+ sample_ticket: Ticket,
+ ticket_repository: TicketRepository,
+) -> None:
+ mock_conn = AsyncMock()
+ mock_conn.execute.side_effect = Exception("DB error")
+ mock_db_context.get_connection.return_value = mock_conn
+
+ with pytest.raises(DbOperationException):
+ await ticket_repository.register_ticket(user=sample_user, ticket=sample_ticket)
+

sample_ticket.id,
sample_user.id,
)
assert result is True
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (code-quality): Simplify comparison to boolean (simplify-boolean-comparison)

Suggested change
assert result is True
assert result

@spuerta10 spuerta10 merged commit a0c4af4 into main Oct 16, 2025
3 checks passed
@spuerta10 spuerta10 deleted the feat/unit-tests branch October 16, 2025 16:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant