310 lines
11 KiB
Python
310 lines
11 KiB
Python
"""Tests for the Catalogue class, which interacts with the library catalogue."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
import pytest
|
|
import requests
|
|
from pytest_mock import MockerFixture
|
|
|
|
from bibapi.catalogue import Catalogue
|
|
|
|
|
|
class TestCatalogue:
|
|
"""Tests for the Catalogue class."""
|
|
|
|
def test_catalogue_initialization(self, mocker: MockerFixture):
|
|
"""Test Catalogue initialization."""
|
|
mocker.patch.object(Catalogue, "check_connection", return_value=True)
|
|
catalogue = Catalogue()
|
|
assert catalogue.timeout == 15
|
|
|
|
def test_catalogue_custom_timeout(self, mocker: MockerFixture):
|
|
"""Test Catalogue initialization with custom timeout."""
|
|
mocker.patch.object(Catalogue, "check_connection", return_value=True)
|
|
catalogue = Catalogue(timeout=30)
|
|
assert catalogue.timeout == 30
|
|
|
|
def test_check_book_exists(self, mocker: MockerFixture):
|
|
"""Test the check_book_exists method of the Catalogue class."""
|
|
mocker.patch.object(Catalogue, "check_connection", return_value=True)
|
|
catalogue = Catalogue()
|
|
|
|
# Mock the get_book_links method to control its output
|
|
mocker.patch.object(
|
|
catalogue,
|
|
"get_book_links",
|
|
return_value=["link1", "link2"],
|
|
)
|
|
|
|
# Test with a known existing book
|
|
existing_book_searchterm = "1693321114"
|
|
assert catalogue.check_book_exists(existing_book_searchterm) is True
|
|
|
|
# Change the mock to return an empty list for non-existing book
|
|
mocker.patch.object(
|
|
catalogue,
|
|
"get_book_links",
|
|
return_value=[],
|
|
)
|
|
|
|
# Test with a known non-existing book
|
|
non_existing_book_searchterm = "00000000009"
|
|
assert catalogue.check_book_exists(non_existing_book_searchterm) is False
|
|
|
|
def test_no_connection_raises_error(self, mocker: MockerFixture):
|
|
"""Test that a ConnectionError is raised with no internet connection."""
|
|
# Mock the check_connection method to simulate no internet connection
|
|
mocker.patch.object(
|
|
Catalogue,
|
|
"check_connection",
|
|
return_value=False,
|
|
)
|
|
|
|
with pytest.raises(ConnectionError, match="No internet connection available."):
|
|
Catalogue()
|
|
|
|
def test_check_connection_success(self, mocker: MockerFixture):
|
|
"""Test check_connection returns True on success."""
|
|
mock_response = MagicMock()
|
|
mock_response.status_code = 200
|
|
mocker.patch("requests.get", return_value=mock_response)
|
|
|
|
catalogue = Catalogue.__new__(Catalogue)
|
|
catalogue.timeout = 15
|
|
assert catalogue.check_connection() is True
|
|
|
|
def test_check_connection_failure(self, mocker: MockerFixture):
|
|
"""Test check_connection handles request exception."""
|
|
mocker.patch(
|
|
"requests.get",
|
|
side_effect=requests.exceptions.RequestException("Network error"),
|
|
)
|
|
|
|
catalogue = Catalogue.__new__(Catalogue)
|
|
catalogue.timeout = 15
|
|
result = catalogue.check_connection()
|
|
assert result is None # Returns None on exception
|
|
|
|
def test_search_book(self, mocker: MockerFixture):
|
|
"""Test search_book method."""
|
|
mocker.patch.object(Catalogue, "check_connection", return_value=True)
|
|
mock_response = MagicMock()
|
|
mock_response.text = "<html>search results</html>"
|
|
mocker.patch("requests.get", return_value=mock_response)
|
|
|
|
catalogue = Catalogue()
|
|
result = catalogue.search_book("test search")
|
|
assert result == "<html>search results</html>"
|
|
|
|
def test_search(self, mocker: MockerFixture):
|
|
"""Test search method."""
|
|
mocker.patch.object(Catalogue, "check_connection", return_value=True)
|
|
mock_response = MagicMock()
|
|
mock_response.text = "<html>detail page</html>"
|
|
mocker.patch("requests.get", return_value=mock_response)
|
|
|
|
catalogue = Catalogue()
|
|
result = catalogue.search("https://example.com/book/123")
|
|
assert result == "<html>detail page</html>"
|
|
|
|
def test_get_book_links(self, mocker: MockerFixture, mock_catalogue_html):
|
|
"""Test get_book_links method."""
|
|
mocker.patch.object(Catalogue, "check_connection", return_value=True)
|
|
mocker.patch.object(
|
|
Catalogue,
|
|
"search_book",
|
|
return_value=mock_catalogue_html,
|
|
)
|
|
|
|
catalogue = Catalogue()
|
|
links = catalogue.get_book_links("test search")
|
|
|
|
assert len(links) == 1
|
|
assert "https://rds.ibs-bw.de/opac/record/123" in links[0]
|
|
|
|
def test_in_library_with_ppn(self, mocker: MockerFixture):
|
|
"""Test in_library method with valid PPN."""
|
|
mocker.patch.object(Catalogue, "check_connection", return_value=True)
|
|
mocker.patch.object(
|
|
Catalogue,
|
|
"get_book_links",
|
|
return_value=["link1"],
|
|
)
|
|
|
|
catalogue = Catalogue()
|
|
assert catalogue.in_library("123456789") is True
|
|
|
|
def test_in_library_without_ppn(self, mocker: MockerFixture):
|
|
"""Test in_library method with None PPN."""
|
|
mocker.patch.object(Catalogue, "check_connection", return_value=True)
|
|
|
|
catalogue = Catalogue()
|
|
assert catalogue.in_library(None) is False
|
|
|
|
def test_in_library_not_found(self, mocker: MockerFixture):
|
|
"""Test in_library method when book not found."""
|
|
mocker.patch.object(Catalogue, "check_connection", return_value=True)
|
|
mocker.patch.object(
|
|
Catalogue,
|
|
"get_book_links",
|
|
return_value=[],
|
|
)
|
|
|
|
catalogue = Catalogue()
|
|
assert catalogue.in_library("nonexistent") is False
|
|
|
|
def test_get_location_none_ppn(self, mocker: MockerFixture):
|
|
"""Test get_location method with None PPN."""
|
|
mocker.patch.object(Catalogue, "check_connection", return_value=True)
|
|
|
|
catalogue = Catalogue()
|
|
assert catalogue.get_location(None) is None
|
|
|
|
def test_get_location_not_found(self, mocker: MockerFixture):
|
|
"""Test get_location when book not found."""
|
|
mocker.patch.object(Catalogue, "check_connection", return_value=True)
|
|
mocker.patch.object(Catalogue, "get_book", return_value=None)
|
|
|
|
catalogue = Catalogue()
|
|
assert catalogue.get_location("123") is None
|
|
|
|
def test_get_ppn(self, mocker: MockerFixture):
|
|
"""Test get_ppn method with valid PPN format."""
|
|
mocker.patch.object(Catalogue, "check_connection", return_value=True)
|
|
mocker.patch.object(
|
|
Catalogue,
|
|
"get_book_links",
|
|
return_value=["https://example.com/opac/record/1234567890"],
|
|
)
|
|
mocker.patch.object(Catalogue, "search", return_value="<html></html>")
|
|
|
|
catalogue = Catalogue()
|
|
ppn = catalogue.get_ppn("test")
|
|
assert ppn == "1234567890"
|
|
|
|
def test_get_ppn_with_x(self, mocker: MockerFixture):
|
|
"""Test get_ppn method with PPN ending in X."""
|
|
mocker.patch.object(Catalogue, "check_connection", return_value=True)
|
|
mocker.patch.object(
|
|
Catalogue,
|
|
"get_book_links",
|
|
return_value=["https://example.com/opac/record/123456789X"],
|
|
)
|
|
mocker.patch.object(Catalogue, "search", return_value="<html></html>")
|
|
|
|
catalogue = Catalogue()
|
|
ppn = catalogue.get_ppn("test")
|
|
assert ppn == "123456789X"
|
|
|
|
def test_get_semesterapparat_number(self, mocker: MockerFixture):
|
|
"""Test get_semesterapparat_number method."""
|
|
mocker.patch.object(Catalogue, "check_connection", return_value=True)
|
|
mocker.patch.object(
|
|
Catalogue,
|
|
"get_book_links",
|
|
return_value=["https://example.com/book"],
|
|
)
|
|
|
|
html = """<html>
|
|
<div class="col-xs-12 rds-dl RDS_LOCATION">
|
|
Semesterapparat-42
|
|
</div>
|
|
</html>"""
|
|
mocker.patch.object(Catalogue, "search", return_value=html)
|
|
|
|
catalogue = Catalogue()
|
|
result = catalogue.get_semesterapparat_number("test")
|
|
assert result == 42
|
|
|
|
def test_get_semesterapparat_number_handbibliothek(self, mocker: MockerFixture):
|
|
"""Test get_semesterapparat_number with Handbibliothek location."""
|
|
mocker.patch.object(Catalogue, "check_connection", return_value=True)
|
|
mocker.patch.object(
|
|
Catalogue,
|
|
"get_book_links",
|
|
return_value=["https://example.com/book"],
|
|
)
|
|
|
|
html = """<html>
|
|
<div class="col-xs-12 rds-dl RDS_LOCATION">
|
|
Floor 1
|
|
|
|
Handbibliothek-Reference
|
|
</div>
|
|
</html>"""
|
|
mocker.patch.object(Catalogue, "search", return_value=html)
|
|
|
|
catalogue = Catalogue()
|
|
result = catalogue.get_semesterapparat_number("test")
|
|
assert "Reference" in str(result) or "Handbibliothek" in str(result)
|
|
|
|
def test_get_semesterapparat_number_not_found(self, mocker: MockerFixture):
|
|
"""Test get_semesterapparat_number when not found."""
|
|
mocker.patch.object(Catalogue, "check_connection", return_value=True)
|
|
mocker.patch.object(Catalogue, "get_book_links", return_value=[])
|
|
|
|
catalogue = Catalogue()
|
|
result = catalogue.get_semesterapparat_number("test")
|
|
assert result == 0
|
|
|
|
def test_get_author(self, mocker: MockerFixture):
|
|
"""Test get_author method."""
|
|
mocker.patch.object(Catalogue, "check_connection", return_value=True)
|
|
mocker.patch.object(
|
|
Catalogue,
|
|
"get_book_links",
|
|
return_value=["https://example.com/book"],
|
|
)
|
|
|
|
html = """<html>
|
|
<div class="col-xs-12 col-md-5 col-lg-4 rds-dl-head RDS_PERSON"></div>
|
|
<div class="col-xs-12 col-md-7 col-lg-8 rds-dl-panel">
|
|
<a href="#">Author One</a>
|
|
<a href="#">Author Two</a>
|
|
</div>
|
|
</html>"""
|
|
mocker.patch.object(Catalogue, "search", return_value=html)
|
|
|
|
catalogue = Catalogue()
|
|
author = catalogue.get_author("kid:123")
|
|
assert "Author One" in author
|
|
assert "Author Two" in author
|
|
assert "; " in author # Separator
|
|
|
|
def test_get_signature(self, mocker: MockerFixture):
|
|
"""Test get_signature method."""
|
|
mocker.patch.object(Catalogue, "check_connection", return_value=True)
|
|
mocker.patch.object(
|
|
Catalogue,
|
|
"get_book_links",
|
|
return_value=["https://example.com/book"],
|
|
)
|
|
|
|
html = """<html>
|
|
<div class="panel-body">
|
|
<div class="rds-dl RDS_SIGNATURE">
|
|
<div class="rds-dl-panel">ABC 123</div>
|
|
</div>
|
|
<div class="rds-dl RDS_STATUS">
|
|
<div class="rds-dl-panel">Available</div>
|
|
</div>
|
|
<div class="rds-dl RDS_LOCATION">
|
|
<div class="rds-dl-panel">Semesterapparat-1</div>
|
|
</div>
|
|
</div>
|
|
</html>"""
|
|
mocker.patch.object(Catalogue, "search", return_value=html)
|
|
|
|
catalogue = Catalogue()
|
|
signature = catalogue.get_signature("9783123456789")
|
|
assert signature == "ABC 123"
|
|
|
|
def test_get_signature_not_found(self, mocker: MockerFixture):
|
|
"""Test get_signature when not found."""
|
|
mocker.patch.object(Catalogue, "check_connection", return_value=True)
|
|
mocker.patch.object(Catalogue, "get_book_links", return_value=[])
|
|
|
|
catalogue = Catalogue()
|
|
signature = catalogue.get_signature("nonexistent")
|
|
assert signature is None
|