Files
BibAPI/tests/test_webrequest.py

310 lines
10 KiB
Python

"""Tests for the webrequest module."""
from unittest.mock import MagicMock, patch
import pytest
import requests
from src.bibapi.webrequest import (
ALLOWED_IPS,
BibTextTransformer,
TransformerType,
WebRequest,
cover,
get_content,
)
class TestTransformerType:
"""Tests for TransformerType enum."""
def test_transformer_type_values(self):
"""Test TransformerType enum values."""
assert TransformerType.ARRAY.value == "ARRAY"
assert TransformerType.COinS.value == "COinS"
assert TransformerType.BibTeX.value == "BibTeX"
assert TransformerType.RIS.value == "RIS"
assert TransformerType.RDS.value == "RDS"
class TestWebRequest:
"""Tests for WebRequest class."""
def test_webrequest_init_not_allowed_ip(self):
"""Test WebRequest raises PermissionError for non-allowed IP."""
with patch("requests.get") as mock_get:
mock_response = MagicMock()
mock_response.text = "192.168.1.1" # Not in ALLOWED_IPS
mock_get.return_value = mock_response
with pytest.raises(PermissionError, match="not allowed"):
WebRequest()
def test_webrequest_init_allowed_ip(self):
"""Test WebRequest initializes successfully with allowed IP."""
with patch("requests.get") as mock_get:
mock_response = MagicMock()
mock_response.text = ALLOWED_IPS[0] # Use first allowed IP
mock_get.return_value = mock_response
wr = WebRequest()
assert wr.public_ip == ALLOWED_IPS[0]
assert wr.timeout == 5
assert wr.use_any is False
def test_webrequest_no_connection(self):
"""Test WebRequest raises ConnectionError when no internet."""
with patch("requests.get") as mock_get:
mock_get.side_effect = requests.exceptions.RequestException("No connection")
with pytest.raises(ConnectionError, match="No internet connection"):
WebRequest()
def test_webrequest_use_any_book(self):
"""Test use_any_book property."""
with patch("requests.get") as mock_get:
mock_response = MagicMock()
mock_response.text = ALLOWED_IPS[0]
mock_get.return_value = mock_response
wr = WebRequest()
result = wr.use_any_book
assert result.use_any is True
def test_webrequest_set_apparat(self):
"""Test set_apparat method."""
with patch("requests.get") as mock_get:
mock_response = MagicMock()
mock_response.text = ALLOWED_IPS[0]
mock_get.return_value = mock_response
wr = WebRequest()
result = wr.set_apparat(5)
assert result.apparat == "05" # Padded with 0
result = wr.set_apparat(15)
assert result.apparat == 15 # Not padded
def test_webrequest_get_ppn(self):
"""Test get_ppn method."""
with patch("requests.get") as mock_get:
mock_response = MagicMock()
mock_response.text = ALLOWED_IPS[0]
mock_get.return_value = mock_response
wr = WebRequest()
# Normal signature
result = wr.get_ppn("ABC 123")
assert result.ppn == "ABC 123"
assert result.signature == "ABC 123"
# Signature with +
result = wr.get_ppn("ABC+123")
assert result.ppn == "ABC%2B123"
# DOI
result = wr.get_ppn("https://doi.org/10.1234/test")
assert result.ppn == "test"
def test_webrequest_search_book(self):
"""Test search_book method."""
with patch("requests.get") as mock_get:
# First call for IP check
ip_response = MagicMock()
ip_response.text = ALLOWED_IPS[0]
# Second call for actual search
search_response = MagicMock()
search_response.text = "<html>results</html>"
mock_get.side_effect = [ip_response, search_response]
wr = WebRequest()
result = wr.search_book("test search")
assert result == "<html>results</html>"
def test_webrequest_search_ppn(self):
"""Test search_ppn method."""
with patch("requests.get") as mock_get:
ip_response = MagicMock()
ip_response.text = ALLOWED_IPS[0]
ppn_response = MagicMock()
ppn_response.text = "<html>ppn result</html>"
mock_get.side_effect = [ip_response, ppn_response]
wr = WebRequest()
result = wr.search_ppn("123456")
assert result == "<html>ppn result</html>"
def test_webrequest_search(self):
"""Test search method."""
with patch("requests.get") as mock_get:
ip_response = MagicMock()
ip_response.text = ALLOWED_IPS[0]
search_response = MagicMock()
search_response.text = "<html>detail page</html>"
mock_get.side_effect = [ip_response, search_response]
wr = WebRequest()
result = wr.search("https://example.com/book")
assert result == "<html>detail page</html>"
def test_webrequest_search_error(self):
"""Test search method handles errors."""
with patch("requests.get") as mock_get:
ip_response = MagicMock()
ip_response.text = ALLOWED_IPS[0]
mock_get.side_effect = [ip_response, requests.exceptions.RequestException()]
wr = WebRequest()
result = wr.search("https://example.com/book")
assert result is None
def test_webrequest_get_book_links(self):
"""Test get_book_links method."""
html = """<html>
<a class="title getFull" href="/opac/book/123">Book 1</a>
<a class="title getFull" href="/opac/book/456">Book 2</a>
</html>"""
with patch("requests.get") as mock_get:
ip_response = MagicMock()
ip_response.text = ALLOWED_IPS[0]
search_response = MagicMock()
search_response.text = html
mock_get.side_effect = [ip_response, search_response]
wr = WebRequest()
wr.ppn = "test"
links = wr.get_book_links("test")
assert len(links) == 2
assert "https://rds.ibs-bw.de/opac/book/123" in links[0]
class TestBibTextTransformer:
"""Tests for BibTextTransformer class."""
def test_bibtexttransformer_init_valid_mode(self):
"""Test BibTextTransformer initialization with valid mode."""
bt = BibTextTransformer(TransformerType.ARRAY)
assert bt.mode == "ARRAY"
def test_bibtexttransformer_init_default_mode(self):
"""Test BibTextTransformer uses ARRAY as default mode."""
bt = BibTextTransformer()
assert bt.mode == "ARRAY"
def test_bibtexttransformer_invalid_mode(self):
"""Test BibTextTransformer raises error for invalid mode."""
# Create a fake invalid mode
class FakeMode:
value = "INVALID"
with pytest.raises(ValueError, match="not valid"):
BibTextTransformer(FakeMode())
def test_bibtexttransformer_use_signature(self):
"""Test use_signature method."""
bt = BibTextTransformer()
result = bt.use_signature("ABC 123")
assert result.signature == "ABC 123"
def test_bibtexttransformer_get_data_none(self):
"""Test get_data with None input."""
bt = BibTextTransformer()
result = bt.get_data(None)
assert result.data is None
def test_bibtexttransformer_get_data_ris(self):
"""Test get_data with RIS format."""
bt = BibTextTransformer(TransformerType.RIS)
data = ["Some data", "TY - BOOK\nTI - Test"]
result = bt.get_data(data)
assert "TY -" in result.data
def test_bibtexttransformer_get_data_array(self):
"""Test get_data with ARRAY format."""
bt = BibTextTransformer(TransformerType.ARRAY)
data = ["Some data", "[kid] => 123456"]
result = bt.get_data(data)
assert "[kid]" in result.data
def test_bibtexttransformer_get_data_coins(self):
"""Test get_data with COinS format."""
bt = BibTextTransformer(TransformerType.COinS)
data = ["Some data", "ctx_ver=Z39.88"]
result = bt.get_data(data)
assert "ctx_ver" in result.data
def test_bibtexttransformer_get_data_bibtex(self):
"""Test get_data with BibTeX format."""
bt = BibTextTransformer(TransformerType.BibTeX)
data = ["Some data", "@book{test2023,"]
result = bt.get_data(data)
assert "@book" in result.data
def test_bibtexttransformer_get_data_rds(self):
"""Test get_data with RDS format."""
bt = BibTextTransformer(TransformerType.RDS)
data = ["Some data", "RDS ---------------------------------- test"]
result = bt.get_data(data)
assert "RDS" in result.data
def test_bibtexttransformer_return_data_none(self):
"""Test return_data when data is None."""
bt = BibTextTransformer()
bt.get_data(None)
result = bt.return_data()
assert result is None
class TestCoverFunction:
"""Tests for the cover function."""
def test_cover_returns_content(self):
"""Test cover function returns image content."""
with patch("requests.get") as mock_get:
mock_response = MagicMock()
mock_response.content = b"fake_image_content"
mock_get.return_value = mock_response
result = cover("9783123456789")
assert result == b"fake_image_content"
def test_cover_url_format(self):
"""Test cover function calls correct URL."""
with patch("requests.get") as mock_get:
mock_response = MagicMock()
mock_response.content = b""
mock_get.return_value = mock_response
cover("9783123456789")
called_url = mock_get.call_args[0][0]
assert "9783123456789" in called_url
assert "buchhandel.de/cover" in called_url
class TestGetContentFunction:
"""Tests for the get_content function."""
def test_get_content(self):
"""Test get_content extracts text from div."""
from bs4 import BeautifulSoup
html = '<html><div class="test-class"> Content Here </div></html>'
soup = BeautifulSoup(html, "html.parser")
result = get_content(soup, "test-class")
assert result == "Content Here"