7a0da7932b
Backwards Compatibility / Verify Encryption Constants (push) Waiting to run
Backwards Compatibility / PyPI Version Compatibility (push) Waiting to run
Backwards Compatibility / Database Migration Tests (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
CodeQL Advanced / Analyze (python) (push) Waiting to run
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Blocked by required conditions
Docker Tests (Consolidated) / detect-changes (push) Waiting to run
Docker Tests (Consolidated) / Build Test Image (push) Waiting to run
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Blocked by required conditions
Docker Tests (Consolidated) / Accessibility Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / LLM Unit Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / LLM Example Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / Production Image Smoke Test (push) Blocked by required conditions
Docker Tests (Consolidated) / Infrastructure Tests (push) Blocked by required conditions
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Waiting to run
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
397 lines
13 KiB
Python
397 lines
13 KiB
Python
"""
|
|
Behavioral tests for json_loader module.
|
|
|
|
Tests the SimpleJSONLoader and extract_strings_from_json function.
|
|
"""
|
|
|
|
import json
|
|
import tempfile
|
|
from pathlib import Path
|
|
|
|
|
|
class TestExtractStringsFromJson:
|
|
"""Tests for extract_strings_from_json function."""
|
|
|
|
def test_extracts_simple_string(self):
|
|
"""Extracts simple string value."""
|
|
from local_deep_research.document_loaders.json_loader import (
|
|
extract_strings_from_json,
|
|
)
|
|
|
|
data = "hello world"
|
|
result = extract_strings_from_json(data)
|
|
assert len(result) == 1
|
|
assert result[0][1] == "hello world"
|
|
|
|
def test_extracts_string_from_dict(self):
|
|
"""Extracts string values from dict."""
|
|
from local_deep_research.document_loaders.json_loader import (
|
|
extract_strings_from_json,
|
|
)
|
|
|
|
data = {"name": "John", "city": "NYC"}
|
|
result = extract_strings_from_json(data)
|
|
assert len(result) == 2
|
|
values = [r[1] for r in result]
|
|
assert "John" in values
|
|
assert "NYC" in values
|
|
|
|
def test_includes_path_for_dict_values(self):
|
|
"""Includes JSON path for dict values."""
|
|
from local_deep_research.document_loaders.json_loader import (
|
|
extract_strings_from_json,
|
|
)
|
|
|
|
data = {"name": "John"}
|
|
result = extract_strings_from_json(data)
|
|
assert result[0][0] == "name"
|
|
assert result[0][1] == "John"
|
|
|
|
def test_extracts_strings_from_list(self):
|
|
"""Extracts strings from list."""
|
|
from local_deep_research.document_loaders.json_loader import (
|
|
extract_strings_from_json,
|
|
)
|
|
|
|
data = ["apple", "banana", "cherry"]
|
|
result = extract_strings_from_json(data)
|
|
assert len(result) == 3
|
|
values = [r[1] for r in result]
|
|
assert "apple" in values
|
|
assert "banana" in values
|
|
assert "cherry" in values
|
|
|
|
def test_includes_index_in_path_for_list(self):
|
|
"""Includes index in path for list items."""
|
|
from local_deep_research.document_loaders.json_loader import (
|
|
extract_strings_from_json,
|
|
)
|
|
|
|
data = ["first", "second"]
|
|
result = extract_strings_from_json(data)
|
|
assert "[0]" in result[0][0]
|
|
assert "[1]" in result[1][0]
|
|
|
|
def test_handles_nested_dict(self):
|
|
"""Handles nested dictionaries."""
|
|
from local_deep_research.document_loaders.json_loader import (
|
|
extract_strings_from_json,
|
|
)
|
|
|
|
data = {"user": {"name": "John", "address": {"city": "NYC"}}}
|
|
result = extract_strings_from_json(data)
|
|
paths = [r[0] for r in result]
|
|
assert "user.name" in paths
|
|
assert "user.address.city" in paths
|
|
|
|
def test_handles_dict_with_list(self):
|
|
"""Handles dict containing list."""
|
|
from local_deep_research.document_loaders.json_loader import (
|
|
extract_strings_from_json,
|
|
)
|
|
|
|
data = {"items": ["a", "b", "c"]}
|
|
result = extract_strings_from_json(data)
|
|
assert len(result) == 3
|
|
paths = [r[0] for r in result]
|
|
assert "items[0]" in paths
|
|
|
|
def test_skips_numbers(self):
|
|
"""Skips numeric values."""
|
|
from local_deep_research.document_loaders.json_loader import (
|
|
extract_strings_from_json,
|
|
)
|
|
|
|
data = {"name": "John", "age": 30}
|
|
result = extract_strings_from_json(data)
|
|
assert len(result) == 1
|
|
assert result[0][1] == "John"
|
|
|
|
def test_skips_booleans(self):
|
|
"""Skips boolean values."""
|
|
from local_deep_research.document_loaders.json_loader import (
|
|
extract_strings_from_json,
|
|
)
|
|
|
|
data = {"name": "John", "active": True}
|
|
result = extract_strings_from_json(data)
|
|
assert len(result) == 1
|
|
assert result[0][1] == "John"
|
|
|
|
def test_skips_null(self):
|
|
"""Skips null values."""
|
|
from local_deep_research.document_loaders.json_loader import (
|
|
extract_strings_from_json,
|
|
)
|
|
|
|
data = {"name": "John", "email": None}
|
|
result = extract_strings_from_json(data)
|
|
assert len(result) == 1
|
|
|
|
def test_returns_empty_for_empty_dict(self):
|
|
"""Returns empty list for empty dict."""
|
|
from local_deep_research.document_loaders.json_loader import (
|
|
extract_strings_from_json,
|
|
)
|
|
|
|
data = {}
|
|
result = extract_strings_from_json(data)
|
|
assert result == []
|
|
|
|
def test_returns_empty_for_empty_list(self):
|
|
"""Returns empty list for empty list."""
|
|
from local_deep_research.document_loaders.json_loader import (
|
|
extract_strings_from_json,
|
|
)
|
|
|
|
data = []
|
|
result = extract_strings_from_json(data)
|
|
assert result == []
|
|
|
|
def test_handles_deeply_nested_structure(self):
|
|
"""Handles deeply nested structure."""
|
|
from local_deep_research.document_loaders.json_loader import (
|
|
extract_strings_from_json,
|
|
)
|
|
|
|
data = {"a": {"b": {"c": {"d": {"e": "value"}}}}}
|
|
result = extract_strings_from_json(data)
|
|
assert len(result) == 1
|
|
assert result[0][0] == "a.b.c.d.e"
|
|
assert result[0][1] == "value"
|
|
|
|
|
|
class TestSimpleJSONLoaderInit:
|
|
"""Tests for SimpleJSONLoader initialization."""
|
|
|
|
def test_accepts_string_path(self):
|
|
"""Accepts string path."""
|
|
from local_deep_research.document_loaders.json_loader import (
|
|
SimpleJSONLoader,
|
|
)
|
|
|
|
loader = SimpleJSONLoader("/path/to/file.json")
|
|
assert loader.file_path == Path("/path/to/file.json")
|
|
|
|
def test_accepts_path_object(self):
|
|
"""Accepts Path object."""
|
|
from local_deep_research.document_loaders.json_loader import (
|
|
SimpleJSONLoader,
|
|
)
|
|
|
|
loader = SimpleJSONLoader(Path("/path/to/file.json"))
|
|
assert loader.file_path == Path("/path/to/file.json")
|
|
|
|
def test_default_encoding_is_utf8(self):
|
|
"""Default encoding is utf-8."""
|
|
from local_deep_research.document_loaders.json_loader import (
|
|
SimpleJSONLoader,
|
|
)
|
|
|
|
loader = SimpleJSONLoader("/path/to/file.json")
|
|
assert loader.encoding == "utf-8"
|
|
|
|
def test_accepts_custom_encoding(self):
|
|
"""Accepts custom encoding."""
|
|
from local_deep_research.document_loaders.json_loader import (
|
|
SimpleJSONLoader,
|
|
)
|
|
|
|
loader = SimpleJSONLoader("/path/to/file.json", encoding="latin-1")
|
|
assert loader.encoding == "latin-1"
|
|
|
|
def test_default_include_paths_is_true(self):
|
|
"""Default include_paths is True."""
|
|
from local_deep_research.document_loaders.json_loader import (
|
|
SimpleJSONLoader,
|
|
)
|
|
|
|
loader = SimpleJSONLoader("/path/to/file.json")
|
|
assert loader.include_paths is True
|
|
|
|
def test_accepts_include_paths_false(self):
|
|
"""Accepts include_paths=False."""
|
|
from local_deep_research.document_loaders.json_loader import (
|
|
SimpleJSONLoader,
|
|
)
|
|
|
|
loader = SimpleJSONLoader("/path/to/file.json", include_paths=False)
|
|
assert loader.include_paths is False
|
|
|
|
|
|
class TestSimpleJSONLoaderLoad:
|
|
"""Tests for SimpleJSONLoader load functionality."""
|
|
|
|
def test_loads_valid_json(self):
|
|
"""Loads valid JSON file."""
|
|
from local_deep_research.document_loaders.json_loader import (
|
|
SimpleJSONLoader,
|
|
)
|
|
|
|
with tempfile.NamedTemporaryFile(
|
|
mode="w", suffix=".json", delete=False
|
|
) as f:
|
|
json.dump({"name": "Test", "value": "Data"}, f)
|
|
f.flush()
|
|
path = f.name
|
|
|
|
try:
|
|
loader = SimpleJSONLoader(path)
|
|
docs = loader.load()
|
|
assert len(docs) == 1
|
|
assert "name: Test" in docs[0].page_content
|
|
assert "value: Data" in docs[0].page_content
|
|
finally:
|
|
Path(path).unlink()
|
|
|
|
def test_includes_source_in_metadata(self):
|
|
"""Includes source path in metadata."""
|
|
from local_deep_research.document_loaders.json_loader import (
|
|
SimpleJSONLoader,
|
|
)
|
|
|
|
with tempfile.NamedTemporaryFile(
|
|
mode="w", suffix=".json", delete=False
|
|
) as f:
|
|
json.dump({"key": "value"}, f)
|
|
f.flush()
|
|
path = f.name
|
|
|
|
try:
|
|
loader = SimpleJSONLoader(path)
|
|
docs = loader.load()
|
|
assert "source" in docs[0].metadata
|
|
assert path in docs[0].metadata["source"]
|
|
finally:
|
|
Path(path).unlink()
|
|
|
|
def test_includes_file_type_in_metadata(self):
|
|
"""Includes file_type in metadata."""
|
|
from local_deep_research.document_loaders.json_loader import (
|
|
SimpleJSONLoader,
|
|
)
|
|
|
|
with tempfile.NamedTemporaryFile(
|
|
mode="w", suffix=".json", delete=False
|
|
) as f:
|
|
json.dump({"key": "value"}, f)
|
|
f.flush()
|
|
path = f.name
|
|
|
|
try:
|
|
loader = SimpleJSONLoader(path)
|
|
docs = loader.load()
|
|
assert docs[0].metadata.get("file_type") == "json"
|
|
finally:
|
|
Path(path).unlink()
|
|
|
|
def test_includes_string_count_in_metadata(self):
|
|
"""Includes string_count in metadata."""
|
|
from local_deep_research.document_loaders.json_loader import (
|
|
SimpleJSONLoader,
|
|
)
|
|
|
|
with tempfile.NamedTemporaryFile(
|
|
mode="w", suffix=".json", delete=False
|
|
) as f:
|
|
json.dump({"a": "1", "b": "2", "c": "3"}, f)
|
|
f.flush()
|
|
path = f.name
|
|
|
|
try:
|
|
loader = SimpleJSONLoader(path)
|
|
docs = loader.load()
|
|
assert docs[0].metadata.get("string_count") == 3
|
|
finally:
|
|
Path(path).unlink()
|
|
|
|
def test_handles_invalid_json(self):
|
|
"""Handles invalid JSON gracefully."""
|
|
from local_deep_research.document_loaders.json_loader import (
|
|
SimpleJSONLoader,
|
|
)
|
|
|
|
with tempfile.NamedTemporaryFile(
|
|
mode="w", suffix=".json", delete=False
|
|
) as f:
|
|
f.write("{ invalid json }")
|
|
f.flush()
|
|
path = f.name
|
|
|
|
try:
|
|
loader = SimpleJSONLoader(path)
|
|
docs = loader.load()
|
|
assert len(docs) == 1
|
|
assert docs[0].metadata.get("parse_error") is True
|
|
finally:
|
|
Path(path).unlink()
|
|
|
|
def test_loads_without_paths(self):
|
|
"""Loads without including paths when include_paths=False."""
|
|
from local_deep_research.document_loaders.json_loader import (
|
|
SimpleJSONLoader,
|
|
)
|
|
|
|
with tempfile.NamedTemporaryFile(
|
|
mode="w", suffix=".json", delete=False
|
|
) as f:
|
|
json.dump({"name": "TestValue"}, f)
|
|
f.flush()
|
|
path = f.name
|
|
|
|
try:
|
|
loader = SimpleJSONLoader(path, include_paths=False)
|
|
docs = loader.load()
|
|
# Should just have the value, not "name: TestValue"
|
|
assert "TestValue" in docs[0].page_content
|
|
# The colon indicates path was included
|
|
assert "name:" not in docs[0].page_content
|
|
finally:
|
|
Path(path).unlink()
|
|
|
|
|
|
class TestExtractTextFromJson:
|
|
"""Tests for extract_text_from_json function."""
|
|
|
|
def test_extracts_text_from_bytes(self):
|
|
"""Extracts text from bytes content."""
|
|
from local_deep_research.document_loaders.json_loader import (
|
|
extract_text_from_json,
|
|
)
|
|
|
|
content = b'{"name": "John", "city": "NYC"}'
|
|
result = extract_text_from_json(content)
|
|
assert "name: John" in result
|
|
assert "city: NYC" in result
|
|
|
|
def test_handles_unicode(self):
|
|
"""Handles Unicode content."""
|
|
from local_deep_research.document_loaders.json_loader import (
|
|
extract_text_from_json,
|
|
)
|
|
|
|
content = '{"greeting": "你好"}'.encode("utf-8")
|
|
result = extract_text_from_json(content)
|
|
assert "你好" in result
|
|
|
|
def test_handles_invalid_json_bytes(self):
|
|
"""Returns raw text for invalid JSON."""
|
|
from local_deep_research.document_loaders.json_loader import (
|
|
extract_text_from_json,
|
|
)
|
|
|
|
content = b"{ not valid json }"
|
|
result = extract_text_from_json(content)
|
|
assert "not valid json" in result
|
|
|
|
def test_uses_custom_encoding(self):
|
|
"""Uses custom encoding when specified."""
|
|
from local_deep_research.document_loaders.json_loader import (
|
|
extract_text_from_json,
|
|
)
|
|
|
|
# Latin-1 encoded content
|
|
content = '{"text": "café"}'.encode("latin-1")
|
|
result = extract_text_from_json(content, encoding="latin-1")
|
|
assert "café" in result
|