"""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)