diff --git a/kjvstudy_org/templates/about.html b/kjvstudy_org/templates/about.html index df8f29e..9fc39dc 100644 --- a/kjvstudy_org/templates/about.html +++ b/kjvstudy_org/templates/about.html @@ -130,9 +130,6 @@
  • Site Statistics — Comprehensive metrics on coverage and content
  • Commentary Index — Browse all verses with in-depth analysis
  • Cross-References Index — Explore Scripture's interconnections
  • -
  • Strong's Concordance — Hebrew and Greek word studies
  • -
  • Study Guides — Thematic studies on biblical topics
  • -
  • Reading Plans — Structured approaches to Scripture reading
  • API Documentation — For developers building on our data
  • diff --git a/pyproject.toml b/pyproject.toml index ebc20d7..f13d17c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,6 +41,7 @@ package = true [dependency-groups] dev = [ "pytest>=8.3.5", + "pytest-cov>=7.0.0", ] [tool.pytest.ini_options] diff --git a/tests/test_utils.py b/tests/test_utils.py new file mode 100644 index 0000000..d7122d8 --- /dev/null +++ b/tests/test_utils.py @@ -0,0 +1,828 @@ +""" +Tests for utility modules - search, books, stories, biographies, etc. +Targeting modules with lower test coverage. +""" +import pytest +from fastapi.testclient import TestClient + + +class TestSearchModule: + """Tests for kjvstudy_org.utils.search module""" + + def test_calculate_relevance_score_single_term(self): + """Test relevance score calculation with single term""" + from kjvstudy_org.utils.search import calculate_relevance_score + + text = "In the beginning God created the heaven and the earth." + score = calculate_relevance_score(text, ["beginning"]) + assert score > 0 + + def test_calculate_relevance_score_multiple_terms(self): + """Test relevance score with multiple search terms""" + from kjvstudy_org.utils.search import calculate_relevance_score + + text = "For God so loved the world" + score = calculate_relevance_score(text, ["god", "loved"]) + # Should get points for both terms + assert score >= 2.0 + + def test_calculate_relevance_score_word_boundaries(self): + """Test that exact word matches get bonus""" + from kjvstudy_org.utils.search import calculate_relevance_score + + text = "God is love" + score_exact = calculate_relevance_score(text, ["love"]) + # Exact word match should have bonus + assert score_exact > 1.0 + + def test_calculate_relevance_score_multiple_occurrences(self): + """Test that multiple occurrences increase score""" + from kjvstudy_org.utils.search import calculate_relevance_score + + text = "The LORD is my shepherd. The LORD is good." + score = calculate_relevance_score(text, ["lord"]) + # Should count both occurrences + assert score >= 2.0 + + def test_highlight_search_terms_basic(self): + """Test basic search term highlighting""" + from kjvstudy_org.utils.search import highlight_search_terms + + text = "For God so loved the world" + highlighted = highlight_search_terms(text, ["god"]) + assert "" in highlighted + assert "" in highlighted + + def test_highlight_search_terms_case_insensitive(self): + """Test case insensitive highlighting""" + from kjvstudy_org.utils.search import highlight_search_terms + + text = "The LORD is my shepherd" + highlighted = highlight_search_terms(text, ["lord"]) + assert "" in highlighted + + def test_highlight_search_terms_multiple(self): + """Test highlighting multiple terms""" + from kjvstudy_org.utils.search import highlight_search_terms + + text = "God is love" + highlighted = highlight_search_terms(text, ["god", "love"]) + # Should have two mark tags + assert highlighted.count("") == 2 + + def test_ensure_search_index(self): + """Test search index initialization""" + from kjvstudy_org.utils.search import ensure_search_index + + # Should return True if FTS available, False otherwise + result = ensure_search_index() + assert isinstance(result, bool) + + def test_perform_full_text_search_verse_reference(self): + """Test search with verse reference""" + from kjvstudy_org.utils.search import perform_full_text_search + + # Test with verse reference format + results = perform_full_text_search("John 3:16") + assert len(results) >= 1 + assert results[0]["book"] == "John" + assert results[0]["chapter"] == 3 + assert results[0]["verse"] == 16 + + def test_perform_full_text_search_regular_query(self): + """Test regular keyword search""" + from kjvstudy_org.utils.search import perform_full_text_search + + results = perform_full_text_search("love", limit=10) + assert len(results) > 0 + # All results should have the search term (or stem) + for result in results: + text_lower = result["text"].lower() + # FTS may use stemming, so check for love/loved/loves + assert "love" in text_lower or "loved" in text_lower or "loves" in text_lower + + +class TestBooksModule: + """Tests for kjvstudy_org.books module""" + + def test_get_book_data_genesis(self): + """Test getting data for Genesis""" + from kjvstudy_org.books import get_book_data + + data = get_book_data("Genesis") + assert data is not None + assert "introduction" in data or "name" in data + + def test_get_book_data_psalms(self): + """Test getting data for Psalms""" + from kjvstudy_org.books import get_book_data + + data = get_book_data("Psalms") + assert data is not None + + def test_get_book_data_invalid(self): + """Test getting data for non-existent book""" + from kjvstudy_org.books import get_book_data + + data = get_book_data("NotABook") + assert data is None + + def test_get_book_introduction(self): + """Test getting book introduction""" + from kjvstudy_org.books import get_book_introduction + + intro = get_book_introduction("Genesis") + # Should return string or None + assert intro is None or isinstance(intro, str) + + def test_get_book_themes(self): + """Test getting book themes""" + from kjvstudy_org.books import get_book_themes + + themes = get_book_themes("Genesis") + # Should return list or None + assert themes is None or isinstance(themes, list) + + def test_get_book_key_verses(self): + """Test getting key verses""" + from kjvstudy_org.books import get_book_key_verses + + verses = get_book_key_verses("John") + assert verses is None or isinstance(verses, list) + + def test_get_book_outline(self): + """Test getting book outline""" + from kjvstudy_org.books import get_book_outline + + outline = get_book_outline("Romans") + assert outline is None or isinstance(outline, list) + + def test_get_book_christ_in_book(self): + """Test getting Christ in book section""" + from kjvstudy_org.books import get_book_christ_in_book + + result = get_book_christ_in_book("Isaiah") + assert result is None or isinstance(result, str) + + def test_get_book_metadata(self): + """Test getting book metadata""" + from kjvstudy_org.books import get_book_metadata + + metadata = get_book_metadata("Matthew") + if metadata: + assert "testament" in metadata or "name" in metadata + + def test_get_book_metadata_invalid(self): + """Test getting metadata for invalid book""" + from kjvstudy_org.books import get_book_metadata + + metadata = get_book_metadata("FakeBook") + assert metadata is None + + def test_get_all_books_metadata(self): + """Test getting all books metadata""" + from kjvstudy_org.books import get_all_books_metadata + + all_books = get_all_books_metadata() + assert isinstance(all_books, list) + # Should have 66 books + assert len(all_books) == 66 + + def test_has_book_data(self): + """Test checking if book has data""" + from kjvstudy_org.books import has_book_data + + assert has_book_data("Genesis") is True + assert has_book_data("NotABook") is False + + def test_get_books_by_category(self): + """Test getting books by category""" + from kjvstudy_org.books import get_books_by_category + + categories = get_books_by_category() + assert isinstance(categories, dict) + # Should have multiple categories + assert len(categories) > 0 + + +class TestStoriesModule: + """Tests for kjvstudy_org.stories module""" + + def test_load_all_stories(self): + """Test loading all stories""" + from kjvstudy_org.stories import load_all_stories + + stories = load_all_stories() + assert isinstance(stories, list) + + def test_get_all_stories_flat(self): + """Test getting flat list of stories""" + from kjvstudy_org.stories import get_all_stories_flat + + stories = get_all_stories_flat() + assert isinstance(stories, list) + if len(stories) > 0: + # Each story should have category info attached + story = stories[0] + assert "category_name" in story or "slug" in story + + def test_get_story_by_slug_exists(self): + """Test getting existing story by slug""" + from kjvstudy_org.stories import get_all_stories_flat, get_story_by_slug + + all_stories = get_all_stories_flat() + if len(all_stories) > 0: + first_slug = all_stories[0].get("slug") + if first_slug: + story = get_story_by_slug(first_slug) + assert story is not None + + def test_get_story_by_slug_not_exists(self): + """Test getting non-existent story""" + from kjvstudy_org.stories import get_story_by_slug + + story = get_story_by_slug("not-a-real-story-slug-12345") + assert story is None + + def test_get_stories_by_category(self): + """Test getting stories by category""" + from kjvstudy_org.stories import load_all_stories, get_stories_by_category + + categories = load_all_stories() + if len(categories) > 0: + cat_slug = categories[0].get("slug") + if cat_slug: + stories = get_stories_by_category(cat_slug) + assert isinstance(stories, list) + + def test_get_stories_by_invalid_category(self): + """Test getting stories from non-existent category""" + from kjvstudy_org.stories import get_stories_by_category + + stories = get_stories_by_category("not-a-real-category") + assert stories == [] + + def test_get_category_by_slug_exists(self): + """Test getting existing category""" + from kjvstudy_org.stories import load_all_stories, get_category_by_slug + + categories = load_all_stories() + if len(categories) > 0: + slug = categories[0].get("slug") + if slug: + category = get_category_by_slug(slug) + assert category is not None + + def test_get_category_by_slug_not_exists(self): + """Test getting non-existent category""" + from kjvstudy_org.stories import get_category_by_slug + + category = get_category_by_slug("fake-category-slug-xyz") + assert category is None + + def test_get_story_count(self): + """Test getting story count""" + from kjvstudy_org.stories import get_story_count + + count = get_story_count() + assert isinstance(count, int) + assert count >= 0 + + def test_get_category_count(self): + """Test getting category count""" + from kjvstudy_org.stories import get_category_count + + count = get_category_count() + assert isinstance(count, int) + assert count >= 0 + + def test_get_categories(self): + """Test getting categories""" + from kjvstudy_org.stories import get_categories + + categories = get_categories() + assert isinstance(categories, list) + + def test_refresh_stories(self): + """Test refreshing story cache""" + from kjvstudy_org.stories import refresh_stories, get_categories + + # Should not raise + refresh_stories() + categories = get_categories() + assert isinstance(categories, list) + + +class TestBiblicalBiographies: + """Tests for kjvstudy_org.biblical_biographies module""" + + def test_get_biography_abraham(self): + """Test getting Abraham's biography""" + from kjvstudy_org.biblical_biographies import get_biography + + bio = get_biography("Abraham") + assert bio is not None + assert isinstance(bio, dict) + + def test_get_biography_david(self): + """Test getting David's biography""" + from kjvstudy_org.biblical_biographies import get_biography + + bio = get_biography("David") + assert bio is not None + + def test_get_biography_not_exists(self): + """Test getting non-existent biography""" + from kjvstudy_org.biblical_biographies import get_biography + + bio = get_biography("Not A Real Person At All") + assert bio is None + + def test_get_biography_via_alias(self): + """Test getting biography via alias name""" + from kjvstudy_org.biblical_biographies import get_biography, BIOGRAPHY_ALIASES + + # If there are aliases, test one + if BIOGRAPHY_ALIASES: + alias = next(iter(BIOGRAPHY_ALIASES.keys())) + bio = get_biography(alias) + # Should either find via alias or return None if canonical not found + # Just verify no crash + assert bio is None or isinstance(bio, dict) + + def test_has_biography_exists(self): + """Test checking existing biography""" + from kjvstudy_org.biblical_biographies import has_biography + + assert has_biography("Abraham") is True + + def test_has_biography_not_exists(self): + """Test checking non-existent biography""" + from kjvstudy_org.biblical_biographies import has_biography + + assert has_biography("Totally Made Up Person") is False + + def test_has_biography_via_alias(self): + """Test checking biography via alias""" + from kjvstudy_org.biblical_biographies import has_biography, BIOGRAPHY_ALIASES + + if BIOGRAPHY_ALIASES: + alias = next(iter(BIOGRAPHY_ALIASES.keys())) + # Should return boolean + result = has_biography(alias) + assert isinstance(result, bool) + + +class TestRedLetterModule: + """Tests for kjvstudy_org.red_letter module""" + + def test_load_red_letter_verses(self): + """Test loading red letter verses""" + from kjvstudy_org.red_letter import load_red_letter_verses + + verses = load_red_letter_verses() + assert isinstance(verses, dict) + + def test_get_christ_words_known_verse(self): + """Test getting Christ's words from known red letter verse""" + from kjvstudy_org.red_letter import get_christ_words + + # John 3:16 - Jesus speaking + words = get_christ_words("John", 3, 16) + # May or may not be marked as red letter depending on data + # Just verify no crash + assert words is None or isinstance(words, str) + + def test_get_christ_words_not_red_letter(self): + """Test verse without Christ's words""" + from kjvstudy_org.red_letter import get_christ_words + + # Genesis 1:1 - Not Jesus speaking + words = get_christ_words("Genesis", 1, 1) + assert words is None + + def test_wrap_red_letter_text_no_words(self): + """Test wrapping text when no Christ words""" + from kjvstudy_org.red_letter import wrap_red_letter_text + + text = "In the beginning God created the heaven and the earth." + result = wrap_red_letter_text(text, "Genesis", 1, 1) + # Should return unchanged if no red letter + assert result == text + + def test_wrap_red_letter_text_full_verse(self): + """Test wrapping full verse red letter""" + from kjvstudy_org.red_letter import wrap_red_letter_text, load_red_letter_verses + + verses = load_red_letter_verses() + # Find a verse marked as 'full' + full_verse = None + for ref, words in verses.items(): + if words == 'full': + full_verse = ref + break + + if full_verse: + # Parse reference + parts = full_verse.rsplit(' ', 1) + if len(parts) == 2: + book = parts[0] + chap_verse = parts[1].split(':') + if len(chap_verse) == 2: + chapter, verse = int(chap_verse[0]), int(chap_verse[1]) + text = "Some verse text" + result = wrap_red_letter_text(text, book, chapter, verse) + assert 'class="words-of-christ"' in result + + +class TestHelpersModule: + """Tests for kjvstudy_org.utils.helpers module""" + + def test_create_slug_basic(self): + """Test basic slug creation""" + from kjvstudy_org.utils.helpers import create_slug + + slug = create_slug("Hello World") + assert slug == "hello-world" + + def test_create_slug_special_chars(self): + """Test slug with special characters""" + from kjvstudy_org.utils.helpers import create_slug + + slug = create_slug("God's Love!") + assert "'" not in slug + assert "!" not in slug + + def test_create_slug_numbers(self): + """Test slug with numbers""" + from kjvstudy_org.utils.helpers import create_slug + + slug = create_slug("John 3:16") + assert isinstance(slug, str) + assert len(slug) > 0 + + def test_is_verse_reference_valid(self): + """Test valid verse reference detection""" + from kjvstudy_org.utils.helpers import is_verse_reference + + assert is_verse_reference("John 3:16") is True + assert is_verse_reference("Genesis 1:1") is True + assert is_verse_reference("1 John 4:8") is True + + def test_is_verse_reference_invalid(self): + """Test invalid verse reference detection""" + from kjvstudy_org.utils.helpers import is_verse_reference + + assert is_verse_reference("hello world") is False + assert is_verse_reference("God is love") is False + + def test_parse_verse_reference_valid(self): + """Test parsing valid verse reference""" + from kjvstudy_org.utils.helpers import parse_verse_reference + + result = parse_verse_reference("John 3:16") + assert result is not None + assert result["book"] == "John" + assert result["chapter"] == 3 + assert result["verse"] == 16 + + def test_parse_verse_reference_invalid(self): + """Test parsing invalid verse reference""" + from kjvstudy_org.utils.helpers import parse_verse_reference + + result = parse_verse_reference("not a verse") + assert result is None + + def test_get_verse_text(self): + """Test getting verse text""" + from kjvstudy_org.utils.helpers import get_verse_text + + text = get_verse_text("John", 3, 16) + assert isinstance(text, str) + assert len(text) > 0 + + def test_get_verse_text_invalid(self): + """Test getting text for invalid verse""" + from kjvstudy_org.utils.helpers import get_verse_text + + text = get_verse_text("FakeBook", 999, 999) + # Should return some fallback string + assert isinstance(text, str) + + def test_get_daily_verse(self): + """Test getting daily verse""" + from kjvstudy_org.utils.helpers import get_daily_verse + + verse = get_daily_verse() + assert isinstance(verse, dict) + assert "book" in verse + assert "chapter" in verse + assert "verse" in verse + assert "text" in verse + + def test_get_chapter_popularity_score(self): + """Test getting chapter popularity score""" + from kjvstudy_org.utils.helpers import get_chapter_popularity_score + + # Psalms 23 should be popular + score = get_chapter_popularity_score("Psalms", 23) + assert isinstance(score, int) + assert 1 <= score <= 10 + + def test_get_chapter_popularity_explanation(self): + """Test getting chapter popularity explanation""" + from kjvstudy_org.utils.helpers import get_chapter_popularity_explanation + + explanation = get_chapter_popularity_explanation("Psalms", 23) + assert isinstance(explanation, str) + assert len(explanation) > 0 + + def test_get_related_content(self): + """Test getting related content""" + from kjvstudy_org.utils.helpers import get_related_content + + related = get_related_content("John", 3, 16) + assert isinstance(related, dict) + assert "study_guides" in related + assert "topics" in related + + +class TestCommentaryLoaderModule: + """Tests for kjvstudy_org.utils.commentary_loader module""" + + def test_load_commentary(self): + """Test loading commentary data""" + from kjvstudy_org.utils.commentary_loader import load_commentary + + commentary = load_commentary() + assert isinstance(commentary, dict) + + def test_load_commentary_flat(self): + """Test loading flat commentary""" + from kjvstudy_org.utils.commentary_loader import load_commentary_flat + + flat = load_commentary_flat() + assert isinstance(flat, dict) + # Keys should be like "Book Chapter:Verse" + if flat: + key = next(iter(flat.keys())) + assert ":" in key + + def test_normalize_entry_valid(self): + """Test normalizing valid entry""" + from kjvstudy_org.utils.commentary_loader import _normalize_entry + + entry = { + "analysis": "Some analysis", + "historical": "Historical context", + "questions": ["Q1", "Q2"] + } + normalized = _normalize_entry(entry) + assert normalized["analysis"] == "Some analysis" + assert normalized["historical"] == "Historical context" + assert len(normalized["questions"]) == 2 + + def test_normalize_entry_with_historical_context(self): + """Test normalizing entry with historical_context key""" + from kjvstudy_org.utils.commentary_loader import _normalize_entry + + entry = { + "analysis": "Analysis", + "historical_context": "Context via alternative key" + } + normalized = _normalize_entry(entry) + assert normalized["historical"] == "Context via alternative key" + + def test_normalize_entry_invalid(self): + """Test normalizing non-dict entry""" + from kjvstudy_org.utils.commentary_loader import _normalize_entry + + result = _normalize_entry("not a dict") + assert result["analysis"] == "" + assert result["historical"] == "" + assert result["questions"] == [] + + def test_slugify(self): + """Test slugify function""" + from kjvstudy_org.utils.commentary_loader import _slugify + + assert _slugify("Genesis") == "genesis" + assert _slugify("1 John") == "1_john" + assert _slugify("Song of Solomon") == "song_of_solomon" + + +class TestInterlinearLoader: + """Tests for kjvstudy_org.interlinear_loader module""" + + def test_get_interlinear_data_genesis(self): + """Test getting interlinear data for Genesis 1:1""" + from kjvstudy_org.interlinear_loader import get_interlinear_data + + data = get_interlinear_data("Genesis", 1, 1) + # Returns list of word data or None + assert data is None or isinstance(data, (dict, list)) + if isinstance(data, list) and len(data) > 0: + # Each item should have word info + assert "original" in data[0] or "english" in data[0] + + def test_get_interlinear_data_john(self): + """Test getting interlinear data for John 1:1""" + from kjvstudy_org.interlinear_loader import get_interlinear_data + + data = get_interlinear_data("John", 1, 1) + assert data is None or isinstance(data, (dict, list)) + + def test_get_interlinear_data_invalid(self): + """Test getting interlinear data for invalid verse""" + from kjvstudy_org.interlinear_loader import get_interlinear_data + + data = get_interlinear_data("FakeBook", 999, 999) + assert data is None + + +class TestCrossReferencesModule: + """Tests for kjvstudy_org.cross_references module""" + + def test_get_cross_references_john_3_16(self): + """Test getting cross references for John 3:16""" + from kjvstudy_org.cross_references import get_cross_references + + refs = get_cross_references("John", 3, 16) + assert isinstance(refs, list) + + def test_get_cross_references_genesis(self): + """Test getting cross references for Genesis 1:1""" + from kjvstudy_org.cross_references import get_cross_references + + refs = get_cross_references("Genesis", 1, 1) + assert isinstance(refs, list) + + def test_get_cross_references_invalid(self): + """Test getting cross references for invalid verse""" + from kjvstudy_org.cross_references import get_cross_references + + refs = get_cross_references("NotABook", 999, 999) + assert isinstance(refs, list) + assert len(refs) == 0 + + +class TestPdfModule: + """Tests for kjvstudy_org.utils.pdf module""" + + def test_weasyprint_available_flag(self): + """Test that WEASYPRINT_AVAILABLE flag is set""" + from kjvstudy_org.utils.pdf import WEASYPRINT_AVAILABLE + + assert isinstance(WEASYPRINT_AVAILABLE, bool) + + def test_render_html_to_pdf_when_available(self): + """Test PDF rendering when weasyprint available""" + from kjvstudy_org.utils.pdf import WEASYPRINT_AVAILABLE, render_html_to_pdf + + if WEASYPRINT_AVAILABLE: + html = "

    Test

    " + pdf_buffer = render_html_to_pdf(html) + assert pdf_buffer is not None + # Should be at position 0 + assert pdf_buffer.tell() == 0 + # Should have PDF content + content = pdf_buffer.read() + assert content.startswith(b'%PDF') + else: + # Should raise RuntimeError when not available + with pytest.raises(RuntimeError): + render_html_to_pdf("") + + def test_render_html_to_pdf_async(self): + """Test async PDF rendering function exists""" + from kjvstudy_org.utils.pdf import WEASYPRINT_AVAILABLE, render_html_to_pdf_async + import asyncio + + # Just verify the async function exists and is callable + assert callable(render_html_to_pdf_async) + + # If weasyprint available, test via sync wrapper + if WEASYPRINT_AVAILABLE: + html = "

    Async Test

    " + # Run async function synchronously for testing + loop = asyncio.new_event_loop() + try: + pdf_buffer = loop.run_until_complete(render_html_to_pdf_async(html)) + assert pdf_buffer is not None + content = pdf_buffer.read() + assert content.startswith(b'%PDF') + finally: + loop.close() + + +class TestTopicsModule: + """Tests for kjvstudy_org.topics module""" + + def test_get_all_topics(self): + """Test getting all topics""" + from kjvstudy_org.topics import get_all_topics + + topics = get_all_topics() + assert isinstance(topics, dict) + assert len(topics) > 0 + + def test_get_topic_valid(self): + """Test getting valid topic""" + from kjvstudy_org.topics import get_all_topics, get_topic + + all_topics = get_all_topics() + if all_topics: + topic_name = next(iter(all_topics.keys())) + topic = get_topic(topic_name) + assert topic is not None + + def test_get_topic_invalid(self): + """Test getting invalid topic""" + from kjvstudy_org.topics import get_topic + + topic = get_topic("not_a_real_topic_xyz123") + assert topic is None + + +class TestStoriesRoutes: + """Tests for kjvstudy_org.routes.stories module""" + + def test_stories_index_page(self, client): + """Test stories index page loads""" + response = client.get("/stories") + assert response.status_code == 200 + assert "Stories" in response.text or "stories" in response.text.lower() + + def test_stories_category_page(self, client): + """Test stories category page""" + from kjvstudy_org.stories import load_all_stories + + categories = load_all_stories() + if categories: + slug = categories[0].get("slug") + if slug: + response = client.get(f"/stories/category/{slug}") + # Should return 200 or redirect + assert response.status_code in [200, 301, 302, 307, 404] + + def test_stories_invalid_category(self, client): + """Test invalid category returns 404""" + response = client.get("/stories/category/not-a-real-category-xyz") + assert response.status_code == 404 + + def test_story_detail_page(self, client): + """Test individual story page""" + from kjvstudy_org.stories import get_all_stories_flat + + stories = get_all_stories_flat() + if stories: + slug = stories[0].get("slug") + if slug: + response = client.get(f"/story/{slug}") + # Should return 200 or 404 + assert response.status_code in [200, 404] + + def test_story_invalid_slug(self, client): + """Test invalid story slug returns 404""" + response = client.get("/story/not-a-real-story-slug-xyz") + assert response.status_code == 404 + + +class TestReadingPlansModule: + """Tests for kjvstudy_org.reading_plans module""" + + def test_get_all_plans(self): + """Test getting all reading plans""" + from kjvstudy_org.reading_plans import get_all_plans + + plans = get_all_plans() + assert isinstance(plans, dict) + assert len(plans) > 0 + + def test_get_plan_by_id(self): + """Test getting reading plan by ID""" + from kjvstudy_org.reading_plans import get_all_plans, get_plan + + plans = get_all_plans() + if plans: + plan_id = next(iter(plans.keys())) + plan = get_plan(plan_id) + assert plan is not None + + def test_get_plan_invalid_id(self): + """Test getting reading plan with invalid ID""" + from kjvstudy_org.reading_plans import get_plan + + plan = get_plan("not-a-real-plan-id-xyz") + assert plan is None + + def test_get_plan_summary(self): + """Test getting plan summary""" + from kjvstudy_org.reading_plans import get_plan_summary + + summary = get_plan_summary() + assert isinstance(summary, list) + assert len(summary) > 0 + # Each item should have name and id + if summary: + assert "name" in summary[0] or "id" in summary[0] diff --git a/uv.lock b/uv.lock index fca4109..309782a 100644 --- a/uv.lock +++ b/uv.lock @@ -493,6 +493,7 @@ dev = [ [package.dev-dependencies] dev = [ { name = "pytest" }, + { name = "pytest-cov" }, ] [package.metadata] @@ -511,7 +512,10 @@ requires-dist = [ provides-extras = ["dev"] [package.metadata.requires-dev] -dev = [{ name = "pytest", specifier = ">=8.3.5" }] +dev = [ + { name = "pytest", specifier = ">=8.3.5" }, + { name = "pytest-cov", specifier = ">=7.0.0" }, +] [[package]] name = "markdown-it-py"