Some checks failed
CI / lint-and-test (push) Failing after 11s
- Upgraded `pytest-asyncio` to version 1.0 to ensure compatibility with the latest features and improvements. - Increased the coverage threshold in pytest configuration to 80%, enhancing the quality assurance process. - Added a new `conftest.py` file to manage shared fixtures and improve test organization. - Introduced multiple new test files to cover various components, ensuring comprehensive test coverage across the application. - Updated the `.coverage` file to reflect the latest coverage metrics.
199 lines
6.0 KiB
Python
199 lines
6.0 KiB
Python
"""Tests for delete_duties_in_range, get_or_create_user_by_full_name, name_manually_edited."""
|
|
|
|
import pytest
|
|
from sqlalchemy import create_engine
|
|
from sqlalchemy.orm import sessionmaker
|
|
|
|
from duty_teller.db.models import Base, User
|
|
from duty_teller.db.repository import (
|
|
delete_duties_in_range,
|
|
get_or_create_user,
|
|
get_or_create_user_by_full_name,
|
|
get_duties,
|
|
insert_duty,
|
|
update_user_display_name,
|
|
)
|
|
|
|
|
|
@pytest.fixture
|
|
def session():
|
|
engine = create_engine(
|
|
"sqlite:///:memory:", connect_args={"check_same_thread": False}
|
|
)
|
|
Base.metadata.create_all(engine)
|
|
Session = sessionmaker(bind=engine, autocommit=False, autoflush=False)
|
|
s = Session()
|
|
try:
|
|
yield s
|
|
finally:
|
|
s.close()
|
|
engine.dispose()
|
|
|
|
|
|
@pytest.fixture
|
|
def user_a(session):
|
|
u = User(
|
|
telegram_user_id=None,
|
|
full_name="User A",
|
|
username=None,
|
|
first_name=None,
|
|
last_name=None,
|
|
)
|
|
session.add(u)
|
|
session.commit()
|
|
session.refresh(u)
|
|
return u
|
|
|
|
|
|
def test_get_or_create_user_by_full_name_creates(session):
|
|
u = get_or_create_user_by_full_name(session, "Новый Пользователь")
|
|
assert u.id is not None
|
|
assert u.full_name == "Новый Пользователь"
|
|
assert u.telegram_user_id is None
|
|
assert u.name_manually_edited is True
|
|
|
|
|
|
def test_get_or_create_user_by_full_name_returns_existing(session, user_a):
|
|
u = get_or_create_user_by_full_name(session, "User A")
|
|
assert u.id == user_a.id
|
|
assert u.full_name == "User A"
|
|
|
|
|
|
def test_delete_duties_in_range_removes_only_in_range(session, user_a):
|
|
# Duties: 2026-02-01 06:00 - 2026-02-02 06:00; 2026-02-15 - 2026-02-16; 2026-02-28 - 2026-03-01
|
|
insert_duty(
|
|
session,
|
|
user_a.id,
|
|
"2026-02-01T06:00:00Z",
|
|
"2026-02-02T06:00:00Z",
|
|
)
|
|
insert_duty(
|
|
session,
|
|
user_a.id,
|
|
"2026-02-15T06:00:00Z",
|
|
"2026-02-16T06:00:00Z",
|
|
)
|
|
insert_duty(
|
|
session,
|
|
user_a.id,
|
|
"2026-02-28T06:00:00Z",
|
|
"2026-03-01T06:00:00Z",
|
|
)
|
|
deleted = delete_duties_in_range(session, user_a.id, "2026-02-10", "2026-02-20")
|
|
assert deleted == 1
|
|
remaining = get_duties(session, "2026-01-01", "2026-03-31")
|
|
assert len(remaining) == 2
|
|
starts = [d[0].start_at for d in remaining]
|
|
assert "2026-02-01T06:00:00Z" in starts
|
|
assert "2026-02-28T06:00:00Z" in starts
|
|
assert "2026-02-15T06:00:00Z" not in starts
|
|
|
|
|
|
def test_delete_duties_in_range_other_user_unchanged(session, user_a):
|
|
user_b = get_or_create_user_by_full_name(session, "User B")
|
|
insert_duty(session, user_a.id, "2026-02-10T06:00:00Z", "2026-02-11T06:00:00Z")
|
|
insert_duty(session, user_b.id, "2026-02-10T06:00:00Z", "2026-02-11T06:00:00Z")
|
|
delete_duties_in_range(session, user_a.id, "2026-02-01", "2026-02-28")
|
|
remaining = get_duties(session, "2026-02-01", "2026-02-28")
|
|
assert len(remaining) == 1
|
|
assert remaining[0][1] == "User B"
|
|
|
|
|
|
def test_get_duties_includes_duty_starting_on_last_day_of_range(session, user_a):
|
|
"""Duty starting on to_date (e.g. 2026-01-31T09:00:00Z) must be included when to_date is 2026-01-31."""
|
|
insert_duty(
|
|
session,
|
|
user_a.id,
|
|
"2026-01-31T09:00:00Z",
|
|
"2026-02-01T09:00:00Z",
|
|
)
|
|
rows = get_duties(session, "2026-01-01", "2026-01-31")
|
|
assert len(rows) == 1
|
|
assert rows[0][0].start_at == "2026-01-31T09:00:00Z"
|
|
assert rows[0][1] == "User A"
|
|
|
|
|
|
def test_get_or_create_user_overwrites_name_when_flag_false(session):
|
|
"""When name_manually_edited is False, second get_or_create_user overwrites name."""
|
|
u1 = get_or_create_user(
|
|
session,
|
|
telegram_user_id=100,
|
|
full_name="First Name",
|
|
username="user1",
|
|
first_name="First",
|
|
last_name="Name",
|
|
)
|
|
assert u1.full_name == "First Name"
|
|
assert u1.name_manually_edited is False
|
|
u2 = get_or_create_user(
|
|
session,
|
|
telegram_user_id=100,
|
|
full_name="Second Name",
|
|
username="user2",
|
|
first_name="Second",
|
|
last_name="Name",
|
|
)
|
|
assert u2.id == u1.id
|
|
assert u2.full_name == "Second Name"
|
|
assert u2.first_name == "Second"
|
|
assert u2.last_name == "Name"
|
|
assert u2.username == "user2"
|
|
|
|
|
|
def test_get_or_create_user_keeps_name_when_flag_true_updates_username(session):
|
|
"""When name_manually_edited is True, get_or_create_user keeps name but updates username."""
|
|
u1 = get_or_create_user(
|
|
session,
|
|
telegram_user_id=200,
|
|
full_name="Custom Name",
|
|
username="old_username",
|
|
first_name="Custom",
|
|
last_name="Name",
|
|
)
|
|
u1.name_manually_edited = True
|
|
session.commit()
|
|
session.refresh(u1)
|
|
u2 = get_or_create_user(
|
|
session,
|
|
telegram_user_id=200,
|
|
full_name="Telegram Name",
|
|
username="new_username",
|
|
first_name="Telegram",
|
|
last_name="Name",
|
|
)
|
|
assert u2.id == u1.id
|
|
assert u2.full_name == "Custom Name"
|
|
assert u2.first_name == "Custom"
|
|
assert u2.last_name == "Name"
|
|
assert u2.username == "new_username"
|
|
|
|
|
|
def test_update_user_display_name_sets_flag_then_get_or_create_user_keeps_name(session):
|
|
"""update_user_display_name sets name and flag; get_or_create_user then does not overwrite name."""
|
|
get_or_create_user(
|
|
session,
|
|
telegram_user_id=300,
|
|
full_name="Original",
|
|
username="u3",
|
|
first_name="Original",
|
|
last_name=None,
|
|
)
|
|
updated = update_user_display_name(
|
|
session, 300, "Manual Name", first_name="Manual", last_name="Name"
|
|
)
|
|
assert updated is not None
|
|
assert updated.full_name == "Manual Name"
|
|
assert updated.name_manually_edited is True
|
|
u_after_sync = get_or_create_user(
|
|
session,
|
|
telegram_user_id=300,
|
|
full_name="From Telegram",
|
|
username="new_u3",
|
|
first_name="From",
|
|
last_name="Telegram",
|
|
)
|
|
assert u_after_sync.full_name == "Manual Name"
|
|
assert u_after_sync.first_name == "Manual"
|
|
assert u_after_sync.last_name == "Name"
|
|
assert u_after_sync.username == "new_u3"
|