"""Tests for StudyCraft engine with mocked LLM.""" from pathlib import Path from unittest.mock import MagicMock, patch from studycraft.engine import StudyCraft def test_run_single_chapter(tmp_path: Path): """Test that engine can generate a single chapter with mocked LLM.""" # Create a simple document doc = tmp_path / "test.txt" doc.write_text("Chapter 1: Introduction\nThis is the content of chapter one.") # Mock LLM response mock_response = MagicMock() mock_response.choices[0].message.content = ( "# Chapter 1: Introduction\n\n" "## 1. Learning Objectives\n" "- Understand the basics\n" "- Learn key concepts\n" "- Apply knowledge\n\n" "## 2. Key Concepts\n...\n\n" "## 3. Worked Examples\n...\n\n" "## 4. Practice Exercises\n...\n\n" "## 5. Mini Project\n...\n\n" "## 6. Further Reading\n...\n\n" "---\n\n" "## Chapter Quiz\n" "1. Question one?\n - A) Answer A\n - B) Answer B\n" "2. Question two?\n - A) Answer A\n - B) Answer B\n" "3. Question three?\n - A) Answer A\n - B) Answer B\n" "4. Question four?\n - A) Answer A\n - B) Answer B\n" "5. Question five?\n - A) Answer A\n - B) Answer B\n" "6. Question six?\n - A) Answer A\n - B) Answer B\n" "7. Question seven?\n - A) Answer A\n - B) Answer B\n" "8. Question eight?\n - A) Answer A\n - B) Answer B\n" "9. Question nine?\n - A) Answer A\n - B) Answer B\n" "10. Question ten?\n - A) Answer A\n - B) Answer B\n" "\n" "## Practice Exercises\n" "1. Exercise one?\n - Solution: ...\n" "2. Exercise two?\n - Solution: ...\n" "3. Exercise three?\n - Solution: ...\n" ) # Patch all external I/O: OpenAI, RAG indexing, web research # Note: `research` is imported in engine.py as `from .researcher import research`, # so we must patch it in the engine module's namespace, not the researcher module. with ( patch("studycraft.engine.OpenAI") as MockOpenAI, patch("studycraft.engine.RAGIndex") as MockRAG, patch("studycraft.engine.research") as MockResearch, ): mock_client = MockOpenAI.return_value mock_client.chat.completions.create.return_value = mock_response MockRAG.return_value.query.return_value = "Relevant context from document" MockResearch.return_value = "Web research results" craft = StudyCraft(api_key="test-key", output_dir=tmp_path / "out") craft.rag = MockRAG.return_value # Replace RAG instance # Run only chapter 1 result = craft.run(doc, only_chapter=1, workers=1) # Check result contains expected formats (export: md, html, pdf/docx/epub) assert isinstance(result, dict) # Markdown file should exist md_files = list(Path(craft.output_dir).glob("*.md")) assert len(md_files) >= 1, "Markdown export missing" # noqa: PT011