tests: add tests for all queries

This commit is contained in:
2026-07-27 00:00:37 +09:00
parent fd1f6c54a4
commit 19c41f2eed
9 changed files with 889 additions and 0 deletions
View File
+38
View File
@@ -0,0 +1,38 @@
from sqlalchemy.orm import Session
from worblehat.models import Author
from worblehat.queries.author import search_authors_by_name
def test_search_authors_by_name_matches_substring_case_insensitively(sql_session: Session) -> None:
tolkien = Author(name="J.R.R. Tolkien")
orwell = Author(name="George Orwell")
sql_session.add_all([tolkien, orwell])
sql_session.flush()
result = search_authors_by_name(sql_session, "tolkien")
assert result == [tolkien]
def test_search_authors_by_name_returns_empty_when_no_match(sql_session: Session) -> None:
sql_session.add(Author(name="Roald Dahl"))
sql_session.flush()
result = search_authors_by_name(sql_session, "nonexistent")
assert result == []
def test_search_authors_by_name_returns_all_matches(sql_session: Session) -> None:
tolkien = Author(name="J.R.R. Tolkien")
orwell = Author(name="George Orwell")
dahl = Author(name="Roald Dahl")
nesbo = Author(name="Jo Nesbø")
nakamura = Author(name="中村 文則")
sql_session.add_all([tolkien, orwell, dahl, nesbo, nakamura])
sql_session.flush()
result = search_authors_by_name(sql_session, "e")
assert set(result) == {tolkien, orwell, nesbo}
+23
View File
@@ -0,0 +1,23 @@
from sqlalchemy.orm import Session
from worblehat.models import Bookcase
from worblehat.queries.bookcase import find_bookcase_by_name
def test_find_bookcase_by_name_returns_match(sql_session: Session) -> None:
bookcase = Bookcase(name="Bookcase A", description="A bookcase")
sql_session.add(bookcase)
sql_session.flush()
result = find_bookcase_by_name(sql_session, "Bookcase A")
assert result is bookcase
def test_find_bookcase_by_name_is_case_sensitive(sql_session: Session) -> None:
sql_session.add(Bookcase(name="Bookcase A"))
sql_session.flush()
result = find_bookcase_by_name(sql_session, "bookcase a")
assert result is None
+115
View File
@@ -0,0 +1,115 @@
from sqlalchemy.orm import Session
from worblehat.models import (
Bookcase,
BookcaseItem,
BookcaseShelf,
MediaType,
)
from worblehat.queries.bookcase_item import (
find_bookcase_item_by_isbn,
find_bookcase_item_by_name,
list_bookcase_items_by_owner,
search_bookcase_item_owners,
search_bookcase_items_by_title,
)
def _make_bookcase_item(
sql_session: Session,
name: str = "Some Book",
isbn: str = "1234567890",
owner: str = "PVV",
) -> BookcaseItem:
media_type = MediaType(name=f"Media type for {name}")
bookcase = Bookcase(name=f"Bookcase for {name}")
shelf = BookcaseShelf(row=0, column=0, bookcase=bookcase)
sql_session.add_all([media_type, bookcase, shelf])
sql_session.flush()
item = BookcaseItem(name, isbn, owner)
item.media_type = media_type
item.shelf = shelf
sql_session.add(item)
sql_session.flush()
return item
def test_find_bookcase_item_by_isbn_returns_match(sql_session: Session) -> None:
item = _make_bookcase_item(sql_session, isbn="1111111111")
result = find_bookcase_item_by_isbn(sql_session, "1111111111")
assert result is item
def test_find_bookcase_item_by_isbn_returns_none_when_missing(sql_session: Session) -> None:
_make_bookcase_item(sql_session, isbn="1111111111")
result = find_bookcase_item_by_isbn(sql_session, "2222222222")
assert result is None
def test_find_bookcase_item_by_name_returns_match(sql_session: Session) -> None:
item = _make_bookcase_item(sql_session, name="Unique Title")
result = find_bookcase_item_by_name(sql_session, "Unique Title")
assert result is item
def test_find_bookcase_item_by_name_returns_none_when_missing(sql_session: Session) -> None:
_make_bookcase_item(sql_session, name="Unique Title")
result = find_bookcase_item_by_name(sql_session, "Other Title")
assert result is None
def test_search_bookcase_items_by_title_matches_substring_case_insensitively(
sql_session: Session,
) -> None:
item = _make_bookcase_item(sql_session, name="The Great Gatsby", isbn="1111111111")
_make_bookcase_item(sql_session, name="Moby Dick", isbn="2222222222")
result = search_bookcase_items_by_title(sql_session, "great gatsby")
assert result == [item]
def test_search_bookcase_items_by_title_returns_empty_when_no_match(sql_session: Session) -> None:
_make_bookcase_item(sql_session, name="The Great Gatsby")
result = search_bookcase_items_by_title(sql_session, "nonexistent")
assert result == []
def test_search_bookcase_item_owners_matches_substring_case_insensitively(
sql_session: Session,
) -> None:
_make_bookcase_item(sql_session, name="Book A", isbn="1111111111", owner="alice")
_make_bookcase_item(sql_session, name="Book B", isbn="2222222222", owner="bob")
result = search_bookcase_item_owners(sql_session, "ALI")
assert result == ["alice"]
def test_search_bookcase_item_owners_returns_distinct_owners(sql_session: Session) -> None:
_make_bookcase_item(sql_session, name="Book A", isbn="1111111111", owner="alice")
_make_bookcase_item(sql_session, name="Book B", isbn="2222222222", owner="alice")
result = search_bookcase_item_owners(sql_session, "ali")
assert result == ["alice"]
def test_list_bookcase_items_by_owner_returns_only_matching_owner(sql_session: Session) -> None:
item_a = _make_bookcase_item(sql_session, name="Book A", isbn="1111111111", owner="alice")
_make_bookcase_item(sql_session, name="Book B", isbn="2222222222", owner="bob")
result = list_bookcase_items_by_owner(sql_session, "alice")
assert result == [item_a]
+92
View File
@@ -0,0 +1,92 @@
from sqlalchemy.orm import Session
from worblehat.models import Bookcase, BookcaseShelf
from worblehat.queries.bookcase_shelf import (
find_bookcase_shelf,
list_bookcase_shelf_positions,
list_bookcase_shelfs_ordered,
)
def test_find_bookcase_shelf_returns_match(sql_session: Session) -> None:
bookcase = Bookcase(name="Bookcase A")
shelf = BookcaseShelf(row=0, column=0, bookcase=bookcase)
sql_session.add_all([bookcase, shelf])
sql_session.flush()
result = find_bookcase_shelf(sql_session, bookcase, column=0, row=0)
assert result is shelf
def test_find_bookcase_shelf_returns_none_for_wrong_position(sql_session: Session) -> None:
bookcase = Bookcase(name="Bookcase A")
shelf = BookcaseShelf(row=0, column=0, bookcase=bookcase)
sql_session.add_all([bookcase, shelf])
sql_session.flush()
assert find_bookcase_shelf(sql_session, bookcase, column=1, row=0) is None
assert find_bookcase_shelf(sql_session, bookcase, column=0, row=1) is None
def test_find_bookcase_shelf_scopes_to_bookcase(sql_session: Session) -> None:
bookcase_a = Bookcase(name="Bookcase A")
bookcase_b = Bookcase(name="Bookcase B")
shelf_a = BookcaseShelf(row=0, column=0, bookcase=bookcase_a)
sql_session.add_all([bookcase_a, bookcase_b, shelf_a])
sql_session.flush()
assert find_bookcase_shelf(sql_session, bookcase_b, column=0, row=0) is None
def test_list_bookcase_shelfs_ordered(sql_session: Session) -> None:
bookcase_b = Bookcase(name="Bookcase B")
bookcase_a = Bookcase(name="Bookcase A")
sql_session.add_all([bookcase_b, bookcase_a])
sql_session.flush()
shelf_b1 = BookcaseShelf(row=1, column=0, bookcase=bookcase_b)
shelf_a2 = BookcaseShelf(row=0, column=2, bookcase=bookcase_a)
shelf_a1 = BookcaseShelf(row=0, column=1, bookcase=bookcase_a)
sql_session.add_all([shelf_b1, shelf_a2, shelf_a1])
sql_session.flush()
result = list_bookcase_shelfs_ordered(sql_session)
assert result == [shelf_a1, shelf_a2, shelf_b1]
def test_list_bookcase_shelf_positions_returns_all_by_default(sql_session: Session) -> None:
bookcase = Bookcase(name="Bookcase A")
shelf_1 = BookcaseShelf(row=0, column=0, bookcase=bookcase)
shelf_2 = BookcaseShelf(row=1, column=1, bookcase=bookcase)
sql_session.add_all([bookcase, shelf_1, shelf_2])
sql_session.flush()
result = list_bookcase_shelf_positions(sql_session, bookcase)
assert set(result) == {(0, 0), (1, 1)}
def test_list_bookcase_shelf_positions_filters_by_column(sql_session: Session) -> None:
bookcase = Bookcase(name="Bookcase A")
shelf_1 = BookcaseShelf(row=0, column=0, bookcase=bookcase)
shelf_2 = BookcaseShelf(row=1, column=1, bookcase=bookcase)
sql_session.add_all([bookcase, shelf_1, shelf_2])
sql_session.flush()
result = list_bookcase_shelf_positions(sql_session, bookcase, column=1)
assert result == [(1, 1)]
def test_list_bookcase_shelf_positions_filters_by_row(sql_session: Session) -> None:
bookcase = Bookcase(name="Bookcase A")
shelf_1 = BookcaseShelf(row=0, column=0, bookcase=bookcase)
shelf_2 = BookcaseShelf(row=1, column=1, bookcase=bookcase)
sql_session.add_all([bookcase, shelf_1, shelf_2])
sql_session.flush()
result = list_bookcase_shelf_positions(sql_session, bookcase, row=1)
assert result == [(1, 1)]
+152
View File
@@ -0,0 +1,152 @@
from datetime import datetime, timedelta
from sqlalchemy.orm import Session
from worblehat.models import (
Bookcase,
BookcaseItem,
BookcaseItemBorrowing,
BookcaseShelf,
MediaType,
)
from worblehat.queries.borrowing import (
has_active_borrowing,
list_active_borrowings,
list_active_borrowings_for_item,
list_borrowings_for_isbn,
list_overdue_borrowings,
)
def _make_bookcase_item(
sql_session: Session,
name: str = "Some Book",
isbn: str = "1234567890",
) -> BookcaseItem:
"""Creates a BookcaseItem along with the MediaType/Bookcase/BookcaseShelf it needs."""
media_type = MediaType(name=f"Media type for {name}")
bookcase = Bookcase(name=f"Bookcase for {name}")
shelf = BookcaseShelf(row=0, column=0, bookcase=bookcase)
sql_session.add_all([media_type, bookcase, shelf])
sql_session.flush()
item = BookcaseItem(name, isbn)
item.media_type = media_type
item.shelf = shelf
sql_session.add(item)
sql_session.flush()
return item
def test_list_active_borrowings_excludes_delivered(sql_session: Session) -> None:
item = _make_bookcase_item(sql_session)
active = BookcaseItemBorrowing("alice", item)
delivered = BookcaseItemBorrowing("bob", item)
delivered.delivered = datetime.now()
sql_session.add_all([active, delivered])
sql_session.flush()
result = list_active_borrowings(sql_session)
assert result == [active]
def test_list_active_borrowings_orders_by_end_time(sql_session: Session) -> None:
item = _make_bookcase_item(sql_session)
later = BookcaseItemBorrowing("alice", item)
later.end_time = datetime.now() + timedelta(days=10)
sooner = BookcaseItemBorrowing("bob", item)
sooner.end_time = datetime.now() + timedelta(days=1)
sql_session.add_all([later, sooner])
sql_session.flush()
result = list_active_borrowings(sql_session)
assert result == [sooner, later]
def test_list_active_borrowings_for_item_scopes_to_item(sql_session: Session) -> None:
item_a = _make_bookcase_item(sql_session, name="Book A", isbn="1111111111")
item_b = _make_bookcase_item(sql_session, name="Book B", isbn="2222222222")
borrowing_a = BookcaseItemBorrowing("alice", item_a)
borrowing_b = BookcaseItemBorrowing("bob", item_b)
sql_session.add_all([borrowing_a, borrowing_b])
sql_session.flush()
result = list_active_borrowings_for_item(sql_session, item_a)
assert result == [borrowing_a]
def test_has_active_borrowing_true_when_undelivered_borrowing_exists(sql_session: Session) -> None:
item = _make_bookcase_item(sql_session)
sql_session.add(BookcaseItemBorrowing("alice", item))
sql_session.flush()
assert has_active_borrowing(sql_session, "alice", item) is True
def test_has_active_borrowing_false_when_delivered(sql_session: Session) -> None:
item = _make_bookcase_item(sql_session)
borrowing = BookcaseItemBorrowing("alice", item)
borrowing.delivered = datetime.now()
sql_session.add(borrowing)
sql_session.flush()
assert has_active_borrowing(sql_session, "alice", item) is False
def test_has_active_borrowing_false_for_other_user(sql_session: Session) -> None:
item = _make_bookcase_item(sql_session)
sql_session.add(BookcaseItemBorrowing("alice", item))
sql_session.flush()
assert has_active_borrowing(sql_session, "bob", item) is False
def test_list_borrowings_for_isbn_scopes_to_isbn(sql_session: Session) -> None:
item_a = _make_bookcase_item(sql_session, name="Book A", isbn="1111111111")
item_b = _make_bookcase_item(sql_session, name="Book B", isbn="2222222222")
borrowing_a = BookcaseItemBorrowing("alice", item_a)
borrowing_b = BookcaseItemBorrowing("bob", item_b)
sql_session.add_all([borrowing_a, borrowing_b])
sql_session.flush()
result = list_borrowings_for_isbn(sql_session, "1111111111")
assert result == [borrowing_a]
def test_list_borrowings_for_isbn_orders_by_username(sql_session: Session) -> None:
item = _make_bookcase_item(sql_session)
borrowing_bob = BookcaseItemBorrowing("bob", item)
borrowing_alice = BookcaseItemBorrowing("alice", item)
sql_session.add_all([borrowing_bob, borrowing_alice])
sql_session.flush()
result = list_borrowings_for_isbn(sql_session, item.isbn)
assert result == [borrowing_alice, borrowing_bob]
def test_list_overdue_borrowings_only_returns_undelivered_past_deadline(
sql_session: Session,
) -> None:
item = _make_bookcase_item(sql_session)
overdue = BookcaseItemBorrowing("alice", item)
overdue.end_time = datetime.now() - timedelta(days=1)
not_yet_due = BookcaseItemBorrowing("bob", item)
not_yet_due.end_time = datetime.now() + timedelta(days=1)
overdue_but_delivered = BookcaseItemBorrowing("carol", item)
overdue_but_delivered.end_time = datetime.now() - timedelta(days=1)
overdue_but_delivered.delivered = datetime.now()
sql_session.add_all([overdue, not_yet_due, overdue_but_delivered])
sql_session.flush()
result = list_overdue_borrowings(sql_session)
assert result == [overdue]
+100
View File
@@ -0,0 +1,100 @@
from datetime import datetime, timedelta
from sqlalchemy.orm import Session
from worblehat.models import (
Bookcase,
BookcaseItem,
BookcaseItemBorrowingQueue,
BookcaseShelf,
MediaType,
)
from worblehat.queries.borrowing_queue import (
is_in_borrowing_queue,
list_all_queue_items,
list_pending_queue_items_for_item,
)
def _make_bookcase_item(
sql_session: Session,
name: str = "Some Book",
isbn: str = "1234567890",
) -> BookcaseItem:
"""Creates a BookcaseItem along with the MediaType/Bookcase/BookcaseShelf it needs."""
media_type = MediaType(name=f"Media type for {name}")
bookcase = Bookcase(name=f"Bookcase for {name}")
shelf = BookcaseShelf(row=0, column=0, bookcase=bookcase)
sql_session.add_all([media_type, bookcase, shelf])
sql_session.flush()
item = BookcaseItem(name, isbn)
item.media_type = media_type
item.shelf = shelf
sql_session.add(item)
sql_session.flush()
return item
def test_list_all_queue_items_orders_by_entered_queue_time(sql_session: Session) -> None:
item = _make_bookcase_item(sql_session)
later = BookcaseItemBorrowingQueue("alice", item)
later.entered_queue_time = datetime.now() + timedelta(hours=1)
sooner = BookcaseItemBorrowingQueue("bob", item)
sooner.entered_queue_time = datetime.now()
sql_session.add_all([later, sooner])
sql_session.flush()
result = list_all_queue_items(sql_session)
assert result == [sooner, later]
def test_is_in_borrowing_queue_true_when_present(sql_session: Session) -> None:
item = _make_bookcase_item(sql_session)
sql_session.add(BookcaseItemBorrowingQueue("alice", item))
sql_session.flush()
assert is_in_borrowing_queue(sql_session, "alice", item) is True
def test_is_in_borrowing_queue_false_for_other_user(sql_session: Session) -> None:
item = _make_bookcase_item(sql_session)
sql_session.add(BookcaseItemBorrowingQueue("alice", item))
sql_session.flush()
assert is_in_borrowing_queue(sql_session, "bob", item) is False
def test_is_in_borrowing_queue_false_when_empty(sql_session: Session) -> None:
item = _make_bookcase_item(sql_session)
sql_session.add(item)
sql_session.flush()
assert is_in_borrowing_queue(sql_session, "alice", item) is False
def test_list_pending_queue_items_for_item_excludes_available_items(sql_session: Session) -> None:
item = _make_bookcase_item(sql_session)
pending = BookcaseItemBorrowingQueue("alice", item)
became_available = BookcaseItemBorrowingQueue("bob", item)
became_available.item_became_available_time = datetime.now()
sql_session.add_all([pending, became_available])
sql_session.flush()
result = list_pending_queue_items_for_item(sql_session, item)
assert result == [pending]
def test_list_pending_queue_items_for_item_scopes_to_item(sql_session: Session) -> None:
item_a = _make_bookcase_item(sql_session, name="Book A", isbn="1111111111")
item_b = _make_bookcase_item(sql_session, name="Book B", isbn="2222222222")
queue_item_a = BookcaseItemBorrowingQueue("alice", item_a)
queue_item_b = BookcaseItemBorrowingQueue("bob", item_b)
sql_session.add_all([queue_item_a, queue_item_b])
sql_session.flush()
result = list_pending_queue_items_for_item(sql_session, item_a)
assert result == [queue_item_a]
+344
View File
@@ -0,0 +1,344 @@
from datetime import datetime, timedelta
from sqlalchemy.orm import Session
from worblehat.models import (
Bookcase,
BookcaseItem,
BookcaseItemBorrowing,
BookcaseItemBorrowingQueue,
BookcaseShelf,
DeadlineDaemonLastRunDatetime,
MediaType,
)
from worblehat.queries.deadline_daemon import (
find_last_run,
find_next_queue_position,
list_close_deadline_borrowings,
list_expiring_queue_positions,
list_newly_available_queue_items,
list_overdue_queue_positions,
list_undelivered_overdue_borrowings,
)
def _make_bookcase_item(
sql_session: Session,
name: str = "Some Book",
isbn: str = "1234567890",
) -> BookcaseItem:
"""Creates a BookcaseItem along with the MediaType/Bookcase/BookcaseShelf it needs."""
media_type = MediaType(name=f"Media type for {name}")
bookcase = Bookcase(name=f"Bookcase for {name}")
shelf = BookcaseShelf(row=0, column=0, bookcase=bookcase)
sql_session.add_all([media_type, bookcase, shelf])
sql_session.flush()
item = BookcaseItem(name, isbn)
item.media_type = media_type
item.shelf = shelf
sql_session.add(item)
sql_session.flush()
return item
def test_find_last_run_returns_none_when_db_is_empty(sql_session: Session) -> None:
assert find_last_run(sql_session) is None
def test_find_last_run_returns_the_single_row(sql_session: Session) -> None:
last_run = DeadlineDaemonLastRunDatetime(time=datetime.now())
sql_session.add(last_run)
sql_session.flush()
assert find_last_run(sql_session) is last_run
def test_list_close_deadline_borrowings_matches_borrowings_ending_in_n_days(
sql_session: Session,
) -> None:
item = _make_bookcase_item(sql_session)
now = datetime.now()
close = BookcaseItemBorrowing("alice", item)
close.end_time = now + timedelta(days=2)
far = BookcaseItemBorrowing("bob", item)
far.end_time = now + timedelta(days=20)
sql_session.add_all([close, far])
sql_session.flush()
result = list_close_deadline_borrowings(
sql_session,
day=2,
last_run_datetime=now - timedelta(minutes=1),
current_run_datetime=now + timedelta(minutes=1),
)
assert result == [close]
def test_list_close_deadline_borrowings_excludes_delivered(sql_session: Session) -> None:
item = _make_bookcase_item(sql_session)
now = datetime.now()
delivered = BookcaseItemBorrowing("alice", item)
delivered.end_time = now + timedelta(days=2)
delivered.delivered = now
sql_session.add(delivered)
sql_session.flush()
result = list_close_deadline_borrowings(
sql_session,
day=2,
last_run_datetime=now - timedelta(minutes=1),
current_run_datetime=now + timedelta(minutes=1),
)
assert result == []
def test_list_undelivered_overdue_borrowings_only_returns_undelivered_past_deadline(
sql_session: Session,
) -> None:
item = _make_bookcase_item(sql_session)
now = datetime.now()
overdue = BookcaseItemBorrowing("alice", item)
overdue.end_time = now - timedelta(days=1)
not_yet_due = BookcaseItemBorrowing("bob", item)
not_yet_due.end_time = now + timedelta(days=1)
overdue_but_delivered = BookcaseItemBorrowing("carol", item)
overdue_but_delivered.end_time = now - timedelta(days=1)
overdue_but_delivered.delivered = now
sql_session.add_all([overdue, not_yet_due, overdue_but_delivered])
sql_session.flush()
result = list_undelivered_overdue_borrowings(sql_session, now)
assert result == [overdue]
def test_list_newly_available_queue_items_requires_delivery_in_window(sql_session: Session) -> None:
item = _make_bookcase_item(sql_session)
now = datetime.now()
borrowing = BookcaseItemBorrowing("alice", item)
borrowing.delivered = now
queue_item = BookcaseItemBorrowingQueue("bob", item)
sql_session.add_all([borrowing, queue_item])
sql_session.flush()
result = list_newly_available_queue_items(
sql_session,
last_run_datetime=now - timedelta(minutes=1),
current_run_datetime=now + timedelta(minutes=1),
)
assert result == [queue_item]
def test_list_newly_available_queue_items_excludes_delivery_outside_window(
sql_session: Session,
) -> None:
item = _make_bookcase_item(sql_session)
now = datetime.now()
borrowing = BookcaseItemBorrowing("alice", item)
borrowing.delivered = now - timedelta(days=10)
queue_item = BookcaseItemBorrowingQueue("bob", item)
sql_session.add_all([borrowing, queue_item])
sql_session.flush()
result = list_newly_available_queue_items(
sql_session,
last_run_datetime=now - timedelta(minutes=1),
current_run_datetime=now + timedelta(minutes=1),
)
assert result == []
def test_list_newly_available_queue_items_excludes_undelivered_borrowings(
sql_session: Session,
) -> None:
item = _make_bookcase_item(sql_session)
now = datetime.now()
borrowing = BookcaseItemBorrowing("alice", item)
queue_item = BookcaseItemBorrowingQueue("bob", item)
sql_session.add_all([borrowing, queue_item])
sql_session.flush()
result = list_newly_available_queue_items(
sql_session,
last_run_datetime=now - timedelta(minutes=1),
current_run_datetime=now + timedelta(minutes=1),
)
assert result == []
def test_list_newly_available_queue_items_excludes_expired_queue_entries(
sql_session: Session,
) -> None:
item = _make_bookcase_item(sql_session)
now = datetime.now()
borrowing = BookcaseItemBorrowing("alice", item)
borrowing.delivered = now
queue_item = BookcaseItemBorrowingQueue("bob", item)
queue_item.expired = True
sql_session.add_all([borrowing, queue_item])
sql_session.flush()
result = list_newly_available_queue_items(
sql_session,
last_run_datetime=now - timedelta(minutes=1),
current_run_datetime=now + timedelta(minutes=1),
)
assert result == []
def test_list_expiring_queue_positions_matches_positions_in_window(sql_session: Session) -> None:
item = _make_bookcase_item(sql_session)
now = datetime.now()
sql_session.add(BookcaseItemBorrowing("someone", item))
in_window = BookcaseItemBorrowingQueue("alice", item)
in_window.item_became_available_time = now
out_of_window = BookcaseItemBorrowingQueue("bob", item)
out_of_window.item_became_available_time = now - timedelta(days=100)
sql_session.add_all([in_window, out_of_window])
sql_session.flush()
result = list_expiring_queue_positions(
sql_session,
last_run_datetime=now - timedelta(days=1),
current_run_datetime=now + timedelta(days=1),
)
assert result == [in_window]
def test_list_expiring_queue_positions_ignores_items_without_a_borrowing(
sql_session: Session,
) -> None:
item = _make_bookcase_item(sql_session)
now = datetime.now()
queue_item = BookcaseItemBorrowingQueue("alice", item)
queue_item.item_became_available_time = now
sql_session.add(queue_item)
sql_session.flush()
result = list_expiring_queue_positions(
sql_session,
last_run_datetime=now - timedelta(days=1),
current_run_datetime=now + timedelta(days=1),
)
assert result == []
def test_list_overdue_queue_positions_matches_positions_older_than_expiry(
sql_session: Session,
) -> None:
item = _make_bookcase_item(sql_session)
now = datetime.now()
overdue = BookcaseItemBorrowingQueue("alice", item)
overdue.item_became_available_time = now - timedelta(days=5)
not_overdue = BookcaseItemBorrowingQueue("bob", item)
not_overdue.item_became_available_time = now
sql_session.add_all([overdue, not_overdue])
sql_session.flush()
result = list_overdue_queue_positions(
sql_session,
queue_position_expiry_days=1,
current_run_datetime=now,
)
assert result == [overdue]
def test_list_overdue_queue_positions_excludes_already_expired(sql_session: Session) -> None:
item = _make_bookcase_item(sql_session)
now = datetime.now()
already_expired = BookcaseItemBorrowingQueue("alice", item)
already_expired.item_became_available_time = now - timedelta(days=5)
already_expired.expired = True
sql_session.add(already_expired)
sql_session.flush()
result = list_overdue_queue_positions(
sql_session,
queue_position_expiry_days=1,
current_run_datetime=now,
)
assert result == []
def test_find_next_queue_position_returns_earliest_pending_entry(sql_session: Session) -> None:
item = _make_bookcase_item(sql_session)
now = datetime.now()
later = BookcaseItemBorrowingQueue("alice", item)
later.entered_queue_time = now + timedelta(hours=1)
sooner = BookcaseItemBorrowingQueue("bob", item)
sooner.entered_queue_time = now
sql_session.add_all([later, sooner])
sql_session.flush()
result = find_next_queue_position(sql_session, item.uid)
assert result is sooner
def test_find_next_queue_position_skips_entries_that_already_became_available(
sql_session: Session,
) -> None:
item = _make_bookcase_item(sql_session)
now = datetime.now()
already_available = BookcaseItemBorrowingQueue("alice", item)
already_available.entered_queue_time = now
already_available.item_became_available_time = now
pending = BookcaseItemBorrowingQueue("bob", item)
pending.entered_queue_time = now + timedelta(hours=1)
sql_session.add_all([already_available, pending])
sql_session.flush()
result = find_next_queue_position(sql_session, item.uid)
assert result is pending
def test_find_next_queue_position_returns_none_when_empty(sql_session: Session) -> None:
item = _make_bookcase_item(sql_session)
result = find_next_queue_position(sql_session, item.uid)
assert result is None
+25
View File
@@ -0,0 +1,25 @@
import pytest
from sqlalchemy.exc import NoResultFound
from sqlalchemy.orm import Session
from worblehat.models import MediaType
from worblehat.queries.media_type import find_media_type_by_name
def test_find_media_type_by_name_returns_match_case_insensitively(sql_session: Session) -> None:
book = MediaType(name="Book", description="A physical book")
comic = MediaType(name="Comic", description="A comic book")
sql_session.add_all([book, comic])
sql_session.flush()
result = find_media_type_by_name(sql_session, "book")
assert result is book
def test_find_media_type_by_name_raises_when_missing(sql_session: Session) -> None:
sql_session.add(MediaType(name="Comic"))
sql_session.flush()
with pytest.raises(NoResultFound):
find_media_type_by_name(sql_session, "book")