213 lines
5.3 KiB
Python
213 lines
5.3 KiB
Python
import pytest
|
|
from unittest import mock
|
|
from datetime import datetime
|
|
|
|
from books.koreader import (
|
|
KoReaderBookColumn,
|
|
build_book_map,
|
|
build_page_data,
|
|
build_scrobbles_from_book_map,
|
|
get_author_str_from_row,
|
|
lookup_or_create_authors_from_author_str,
|
|
create_book_from_row,
|
|
process_koreader_sqlite_file,
|
|
)
|
|
|
|
|
|
@pytest.mark.django_db
|
|
@mock.patch("requests.get")
|
|
def test_build_book_map(get_mock, koreader_rows, valid_response):
|
|
get_mock.return_value = valid_response
|
|
book_map = build_book_map(koreader_rows.BOOK_ROWS)
|
|
assert len(book_map) == 1
|
|
|
|
|
|
@pytest.mark.django_db
|
|
@mock.patch("requests.get")
|
|
def test_load_page_data_to_map(get_mock, koreader_rows, valid_response):
|
|
get_mock.return_value = valid_response
|
|
book_map = build_page_data(
|
|
koreader_rows.PAGE_STATS_ROWS,
|
|
build_book_map(koreader_rows.BOOK_ROWS),
|
|
)
|
|
assert (
|
|
len(book_map[1]["pages"])
|
|
== koreader_rows.BOOK_ROWS[0][KoReaderBookColumn.TOTAL_READ_PAGES.value]
|
|
)
|
|
|
|
|
|
@pytest.mark.django_db
|
|
@mock.patch("requests.get")
|
|
def test_build_scrobbles_from_pages(get_mock, koreader_rows, demo_user, valid_response):
|
|
get_mock.return_value = valid_response
|
|
book_map = build_book_map(koreader_rows.BOOK_ROWS)
|
|
book_map = build_page_data(koreader_rows.PAGE_STATS_ROWS, book_map)
|
|
|
|
scrobbles = build_scrobbles_from_book_map(book_map, demo_user)
|
|
# The test data generator adds the session-gap 3600s AFTER the trigger page
|
|
# (not before), so the first session includes 21 pages (1-21), and each
|
|
# subsequent session has 20 until the last. The last page is now included
|
|
# in the final scrobble instead of being orphaned.
|
|
expected_scrobbles = 6 * len(book_map.keys())
|
|
assert len(scrobbles) == expected_scrobbles
|
|
assert len(scrobbles[0].logdata.page_data.keys()) == 21
|
|
assert len(scrobbles[1].logdata.page_data.keys()) == 20
|
|
assert len(scrobbles[2].logdata.page_data.keys()) == 20
|
|
assert len(scrobbles[3].logdata.page_data.keys()) == 20
|
|
assert len(scrobbles[4].logdata.page_data.keys()) == 20
|
|
assert len(scrobbles[5].logdata.page_data.keys()) == 19
|
|
|
|
|
|
def test_get_author_str_from_row():
|
|
row = [
|
|
1,
|
|
"Test Book",
|
|
"John Smith\nJane Doe",
|
|
0,
|
|
0,
|
|
0,
|
|
300,
|
|
"",
|
|
"",
|
|
"abc123",
|
|
0,
|
|
120,
|
|
]
|
|
result = get_author_str_from_row(row)
|
|
assert result == "John Smith, Jane Doe"
|
|
|
|
|
|
def test_get_author_str_from_row_strips_middle_initials():
|
|
row = [
|
|
1,
|
|
"Test Book",
|
|
"John A. Smith",
|
|
0,
|
|
0,
|
|
0,
|
|
300,
|
|
"",
|
|
"",
|
|
"abc123",
|
|
0,
|
|
120,
|
|
]
|
|
result = get_author_str_from_row(row)
|
|
assert result == "John Smith"
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_lookup_or_create_authors_from_author_str_creates_new_author():
|
|
author = lookup_or_create_authors_from_author_str("New Author")
|
|
assert len(author) == 1
|
|
assert author[0].name == "New Author"
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_lookup_or_create_authors_from_author_str_finds_existing():
|
|
from books.models import Author
|
|
|
|
Author.objects.create(name="Existing Author")
|
|
author = lookup_or_create_authors_from_author_str("Existing Author")
|
|
assert len(author) == 1
|
|
assert author[0].name == "Existing Author"
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_lookup_or_create_authors_from_author_str_ignores_na():
|
|
author = lookup_or_create_authors_from_author_str("N/A")
|
|
assert len(author) == 0
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_lookup_or_create_authors_from_author_str_handles_multiple():
|
|
author = lookup_or_create_authors_from_author_str("Author One, Author Two")
|
|
assert len(author) == 2
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_create_book_from_row():
|
|
row = [
|
|
1,
|
|
"Test Book - Author Name",
|
|
"Test Author",
|
|
0,
|
|
0,
|
|
0,
|
|
300,
|
|
"",
|
|
"",
|
|
"abc123def456",
|
|
3600,
|
|
120,
|
|
]
|
|
book = create_book_from_row(row)
|
|
assert book.title == "Test Book"
|
|
assert book.pages == 300
|
|
assert "abc123def456" in book.koreader_data_by_hash
|
|
assert book.authors.count() == 1
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_create_book_from_row_handles_title_with_author_suffix():
|
|
row = [
|
|
1,
|
|
"Test Book - Author_Name",
|
|
"N/A",
|
|
0,
|
|
0,
|
|
0,
|
|
300,
|
|
"",
|
|
"",
|
|
"abc123def456",
|
|
3600,
|
|
120,
|
|
]
|
|
book = create_book_from_row(row)
|
|
assert book.title == "Test Book"
|
|
assert book.authors.count() == 1
|
|
assert book.authors.first().name == "Author"
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_create_book_from_row_handles_null_bytes():
|
|
row = [
|
|
1,
|
|
"Test\x00Book",
|
|
"Test\x00Author",
|
|
0,
|
|
0,
|
|
0,
|
|
300,
|
|
"",
|
|
"",
|
|
"abc123def456",
|
|
3600,
|
|
120,
|
|
]
|
|
book = create_book_from_row(row)
|
|
assert "TestBook" in book.title
|
|
assert "TestAuthor" in book.authors.first().name
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_build_book_map_ignores_garbage_titles(koreader_rows):
|
|
garbage_row = [
|
|
999,
|
|
"KOReader Quickstart Guide",
|
|
"N/A",
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
"",
|
|
"",
|
|
"garbage123",
|
|
0,
|
|
0,
|
|
]
|
|
book_map = build_book_map(koreader_rows.BOOK_ROWS + [garbage_row])
|
|
assert len(book_map) == 1
|
|
assert 999 not in book_map
|