This commit is contained in:
309
tests/test_webrequest.py
Normal file
309
tests/test_webrequest.py
Normal file
@@ -0,0 +1,309 @@
|
||||
"""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="IP 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"
|
||||
Reference in New Issue
Block a user