import pytest import json from scrapling import Selector from scrapling.core.custom_types import AttributesHandler class TestAttributesHandler: """Test AttributesHandler functionality""" @pytest.fixture def sample_html(self): return """
"""
@pytest.fixture
def attributes(self, sample_html):
page = Selector(sample_html)
element = page.css("#main")[0]
return element.attrib
def test_basic_attribute_access(self, attributes):
"""Test basic attribute access"""
# Dict-like access
assert attributes["id"] == "main"
assert attributes["class"] == "container active"
assert attributes["title"] == "Main Container"
# Key existence
assert "id" in attributes
assert "nonexistent" not in attributes
# Get with default
assert attributes.get("id") == "main"
assert attributes.get("nonexistent") is None
assert attributes.get("nonexistent", "default") == "default"
def test_iteration_methods(self, attributes):
"""Test iteration over attributes"""
# Keys
keys = list(attributes.keys())
assert "id" in keys
assert "class" in keys
assert "data-config" in keys
# Values
values = list(attributes.values())
assert "main" in values
assert "container active" in values
# Items
items = dict(attributes.items())
assert items["id"] == "main"
assert items["class"] == "container active"
# Length
assert len(attributes) > 0
def test_json_parsing(self, attributes):
"""Test JSON parsing from attributes"""
# Valid JSON object
config = attributes["data-config"].json()
assert config["theme"] == "dark"
assert config["version"] == 2.5
# Valid JSON array
items = attributes["data-items"].json()
assert items == [1, 2, 3, 4, 5]
# Nested JSON
nested = attributes["data-nested"].json()
assert nested["user"]["name"] == "John"
assert nested["user"]["age"] == 30
# JSON null
assert attributes["data-null"].json() is None
def test_json_error_handling(self, attributes):
"""Test JSON parsing error handling"""
# Invalid JSON should raise error or return None
with pytest.raises((json.JSONDecodeError, AttributeError)):
attributes["data-invalid-json"].json()
# Non-existent attribute
with pytest.raises(KeyError):
attributes["nonexistent"].json()
def test_json_string_property(self, attributes):
"""Test json_string property"""
# Should return JSON representation of all attributes
json_string = attributes.json_string
assert isinstance(json_string, bytes)
# Parse it back
parsed = json.loads(json_string)
assert parsed["id"] == "main"
assert parsed["class"] == "container active"
def test_search_values(self, attributes):
"""Test search_values method"""
# Exact match
results = list(attributes.search_values("main", partial=False))
assert len(results) == 1
assert "id" in results[0]
# Partial match
results = list(attributes.search_values("container", partial=True))
assert len(results) >= 1
found_keys = []
for result in results:
found_keys.extend(result.keys())
assert "class" in found_keys or "title" in found_keys
# Case sensitivity
results = list(attributes.search_values("MAIN", partial=False))
assert len(results) == 0 # Should be case-sensitive by default
# Multiple matches
results = list(attributes.search_values("2", partial=True))
assert len(results) > 1 # Should find multiple attributes
# No matches
results = list(attributes.search_values("nonexistent", partial=False))
assert len(results) == 0
def test_special_attribute_types(self, sample_html):
"""Test handling of special attribute types"""
page = Selector(sample_html)
# Boolean attributes
input_elem = page.css("input")[0]
assert "required" in input_elem.attrib
assert "disabled" in input_elem.attrib
# Empty attributes
main_elem = page.css("#main")[0]
assert main_elem.attrib["data-empty"] == ""
# Numeric string attributes
assert main_elem.attrib["data-number"] == "42"
assert main_elem.attrib["data-bool"] == "true"
def test_attribute_modification(self, sample_html):
"""Test that AttributesHandler is read-only (if applicable)"""
page = Selector(sample_html)
element = page.css("#main")[0]
attrs = element.attrib
# Test if attributes can be modified
# This behavior depends on implementation
original_id = attrs["id"]
try:
attrs["id"] = "new-id"
# If modification is allowed
assert attrs["id"] == "new-id"
# Reset
attrs["id"] = original_id
except (TypeError, AttributeError):
# If modification is not allowed (read-only)
assert attrs["id"] == original_id
def test_string_representation(self, attributes):
"""Test string representations"""
# __str__
str_repr = str(attributes)
assert isinstance(str_repr, str)
assert "id" in str_repr or "main" in str_repr
# __repr__
repr_str = repr(attributes)
assert isinstance(repr_str, str)
def test_edge_cases(self, sample_html):
"""Test edge cases and special scenarios"""
page = Selector(sample_html)
# Element with no attributes
page_with_no_attrs = Selector("