Files
paperlib/tests/test_json_output.py
2026-04-17 19:27:16 -04:00

291 lines
9.8 KiB
Python

"""Tests for JSON output functionality."""
import json
import subprocess
from pathlib import Path
import pytest
from paperlib.models import PaperMetadata, SourceType
from paperlib.utils import JSONOutputMixin
class TestJSONOutputMixin:
"""Test JSONOutputMixin utility functions."""
def test_format_metadata_for_json(self):
"""Test formatting PaperMetadata for JSON output."""
metadata = PaperMetadata(
paper_id="test-paper-1",
source_type=SourceType.ARXIV,
source_id="2212.06340",
title="Test Paper",
authors=["Alice Smith", "Bob Jones"],
categories=["cs.AI"],
)
result = JSONOutputMixin.format_metadata_for_json(metadata)
assert result["paper_id"] == "test-paper-1"
assert result["source_type"] == "arxiv"
assert result["source_id"] == "2212.06340"
assert result["title"] == "Test Paper"
assert result["authors"] == ["Alice Smith", "Bob Jones"]
assert result["categories"] == ["cs.AI"]
def test_format_metadata_for_json_dict(self):
"""Test formatting dict metadata for JSON output."""
metadata_dict = {
"paper_id": "test-paper-1",
"title": "Test Paper",
"source_type": "local",
}
result = JSONOutputMixin.format_metadata_for_json(metadata_dict)
assert result == metadata_dict
def test_format_papers_list_for_json(self):
"""Test formatting a list of papers for JSON output."""
papers = [
PaperMetadata(
paper_id="paper-1",
source_type=SourceType.LOCAL,
title="Paper 1",
),
PaperMetadata(
paper_id="paper-2",
source_type=SourceType.ARXIV,
title="Paper 2",
),
]
result = JSONOutputMixin.format_papers_list_for_json(papers)
assert "papers" in result
assert "total" in result
assert result["total"] == 2
assert len(result["papers"]) == 2
assert result["papers"][0]["paper_id"] == "paper-1"
assert result["papers"][1]["paper_id"] == "paper-2"
class TestCLIJSONOutput:
"""Test CLI commands with JSON output."""
def run_paperlib_cmd(self, *args):
"""Helper to run paperlib commands and parse JSON output."""
cmd = ["uv", "run", "paperlib"] + list(args)
result = subprocess.run(cmd, capture_output=True, text=True, cwd=Path.cwd())
if "--json" in args:
try:
output_data = json.loads(result.stdout)
return result.returncode, output_data, result.stderr
except json.JSONDecodeError as e:
pytest.fail(f"Invalid JSON output: {e}\nOutput: {result.stdout}")
return result.returncode, result.stdout, result.stderr
def test_status_json_output(self):
"""Test status command with JSON output."""
# Create temporary library
temp_lib = Path("./.tmp") / f"test_status_json_{hash(self)}"
temp_lib.mkdir(parents=True, exist_ok=True)
try:
# Initialize library
self.run_paperlib_cmd("init", str(temp_lib))
# Test status with JSON
returncode, output_data, stderr = self.run_paperlib_cmd(
"status", "--library", str(temp_lib), "--json"
)
assert returncode == 0
assert isinstance(output_data, dict)
assert output_data["success"] is True
assert "timestamp" in output_data
assert "library_root" in output_data
assert "config_path" in output_data
assert "database_path" in output_data
assert str(temp_lib.resolve()) in output_data["library_root"]
finally:
if temp_lib.exists():
import shutil
shutil.rmtree(temp_lib)
def test_list_json_output_empty(self):
"""Test list command with JSON output for empty library."""
temp_lib = Path("./.tmp") / f"test_list_json_{hash(self)}"
temp_lib.mkdir(parents=True, exist_ok=True)
try:
# Initialize library
self.run_paperlib_cmd("init", str(temp_lib))
# Test list with JSON
returncode, output_data, stderr = self.run_paperlib_cmd(
"list", "--library", str(temp_lib), "--json"
)
assert returncode == 0
assert isinstance(output_data, dict)
assert output_data["success"] is True
assert output_data["papers"] == []
assert output_data["total"] == 0
finally:
if temp_lib.exists():
import shutil
shutil.rmtree(temp_lib)
def test_import_json_output(self):
"""Test import command with JSON output."""
temp_lib = Path("./.tmp") / f"test_import_json_{hash(self)}"
temp_lib.mkdir(parents=True, exist_ok=True)
# Create sample PDF
sample_pdf = Path("./.tmp") / f"test_import_json_{hash(self)}.pdf"
with sample_pdf.open("wb") as f:
f.write(b"%PDF-1.4\n%%EOF\n")
try:
# Initialize library
self.run_paperlib_cmd("init", str(temp_lib))
# Test import with JSON
returncode, output_data, stderr = self.run_paperlib_cmd(
"import",
"--pdf",
str(sample_pdf),
"--title",
"Test JSON Import",
"--library",
str(temp_lib),
"--json",
)
assert returncode == 0
assert isinstance(output_data, dict)
assert output_data["success"] is True
assert "paper_id" in output_data
assert output_data["title"] == "Test JSON Import"
assert output_data["source_type"] == "local"
assert "Successfully imported local PDF" in output_data["message"]
assert "paper" in output_data
assert isinstance(output_data["paper"], dict)
finally:
if temp_lib.exists():
import shutil
shutil.rmtree(temp_lib)
if sample_pdf.exists():
sample_pdf.unlink()
def test_show_json_output(self):
"""Test show command with JSON output."""
temp_lib = Path("./.tmp") / f"test_show_json_{hash(self)}"
temp_lib.mkdir(parents=True, exist_ok=True)
# Create sample PDF
sample_pdf = Path("./.tmp") / f"test_show_json_{hash(self)}.pdf"
with sample_pdf.open("wb") as f:
f.write(b"%PDF-1.4\n%%EOF\n")
try:
# Initialize and import
self.run_paperlib_cmd("init", str(temp_lib))
import_returncode, import_data, _ = self.run_paperlib_cmd(
"import",
"--pdf",
str(sample_pdf),
"--title",
"Test JSON Show",
"--library",
str(temp_lib),
"--json",
)
assert import_returncode == 0
paper_id = import_data["paper_id"]
# Test show with JSON
returncode, output_data, stderr = self.run_paperlib_cmd(
"show", paper_id, "--library", str(temp_lib), "--json"
)
assert returncode == 0
assert isinstance(output_data, dict)
assert output_data["success"] is True
assert "paper" in output_data
assert output_data["paper"]["paper_id"] == paper_id
assert output_data["paper"]["title"] == "Test JSON Show"
assert "files_status" in output_data["paper"]
assert "pdf_exists" in output_data["paper"]["files_status"]
finally:
if temp_lib.exists():
import shutil
shutil.rmtree(temp_lib)
if sample_pdf.exists():
sample_pdf.unlink()
def test_show_json_not_found(self):
"""Test show command with JSON output for non-existent paper."""
temp_lib = Path("./.tmp") / f"test_show_json_nf_{hash(self)}"
temp_lib.mkdir(parents=True, exist_ok=True)
try:
# Initialize library
self.run_paperlib_cmd("init", str(temp_lib))
# Test show non-existent paper
returncode, output_data, stderr = self.run_paperlib_cmd(
"show", "nonexistent", "--library", str(temp_lib), "--json"
)
assert returncode == 1
assert isinstance(output_data, dict)
assert output_data["success"] is False
assert "error" in output_data
assert "Paper not found" in output_data["error"]
finally:
if temp_lib.exists():
import shutil
shutil.rmtree(temp_lib)
def test_convert_json_output(self):
"""Test convert command with JSON output."""
temp_lib = Path("./.tmp") / f"test_convert_json_{hash(self)}"
temp_lib.mkdir(parents=True, exist_ok=True)
try:
# Initialize library
self.run_paperlib_cmd("init", str(temp_lib))
# Test convert with no papers (JSON)
returncode, output_data, stderr = self.run_paperlib_cmd(
"convert", "--library", str(temp_lib), "--json"
)
assert returncode == 0
assert isinstance(output_data, dict)
assert output_data["success"] is True
assert output_data["action"] == "convert_pending"
assert output_data["success_count"] == 0
assert output_data["failure_count"] == 0
assert output_data["total_attempted"] == 0
finally:
if temp_lib.exists():
import shutil
shutil.rmtree(temp_lib)