diff --git a/kjvstudy_org/data/verse_commentary/exodus.json b/kjvstudy_org/data/verse_commentary/exodus.json index 611ff6f..201d663 100644 --- a/kjvstudy_org/data/verse_commentary/exodus.json +++ b/kjvstudy_org/data/verse_commentary/exodus.json @@ -6558,9 +6558,7 @@ "analysis": "The consecration ram's blood applied to Aaron's right ear, thumb, and toe symbolizes that priests must hear God's word (ear), act on it (thumb/hand), and walk in it (toe/foot). Blood application sanctifies these members for holy service. Christ's blood sanctifies our hearing, working, and walking—our complete life consecrated through His atonement. The right side emphasizes the place of honor and strength.", "historical": "The blood application ceremony was unique to priestly consecration, marking the priests as blood-sanctified for service. This visible sign testified to their cleansing and separation for God's purposes.", "questions": [ - [ - "How does Christ's blood sanctify your hearing, working, and walking?" - ], + "How does Christ's blood sanctify your hearing, working, and walking?", "What does the 'right' (ear, hand, foot) emphasis teach about strength in service?" ] }, @@ -6568,9 +6566,7 @@ "analysis": "The consecration ram's blood applied to Aaron's right ear, thumb, and toe symbolizes that priests must hear God's word (ear), act on it (thumb/hand), and walk in it (toe/foot). Blood application sanctifies these members for holy service. Christ's blood sanctifies our hearing, working, and walking—our complete life consecrated through His atonement. The right side emphasizes the place of honor and strength.", "historical": "The blood application ceremony was unique to priestly consecration, marking the priests as blood-sanctified for service. This visible sign testified to their cleansing and separation for God's purposes.", "questions": [ - [ - "How does Christ's blood sanctify your hearing, working, and walking?" - ], + "How does Christ's blood sanctify your hearing, working, and walking?", "What does the 'right' (ear, hand, foot) emphasis teach about strength in service?" ] }, @@ -6578,9 +6574,7 @@ "analysis": "The consecration ram's blood applied to Aaron's right ear, thumb, and toe symbolizes that priests must hear God's word (ear), act on it (thumb/hand), and walk in it (toe/foot). Blood application sanctifies these members for holy service. Christ's blood sanctifies our hearing, working, and walking—our complete life consecrated through His atonement. The right side emphasizes the place of honor and strength.", "historical": "The blood application ceremony was unique to priestly consecration, marking the priests as blood-sanctified for service. This visible sign testified to their cleansing and separation for God's purposes.", "questions": [ - [ - "How does Christ's blood sanctify your hearing, working, and walking?" - ], + "How does Christ's blood sanctify your hearing, working, and walking?", "What does the 'right' (ear, hand, foot) emphasis teach about strength in service?" ] }, @@ -6588,9 +6582,7 @@ "analysis": "The consecration ram's blood applied to Aaron's right ear, thumb, and toe symbolizes that priests must hear God's word (ear), act on it (thumb/hand), and walk in it (toe/foot). Blood application sanctifies these members for holy service. Christ's blood sanctifies our hearing, working, and walking—our complete life consecrated through His atonement. The right side emphasizes the place of honor and strength.", "historical": "The blood application ceremony was unique to priestly consecration, marking the priests as blood-sanctified for service. This visible sign testified to their cleansing and separation for God's purposes.", "questions": [ - [ - "How does Christ's blood sanctify your hearing, working, and walking?" - ], + "How does Christ's blood sanctify your hearing, working, and walking?", "What does the 'right' (ear, hand, foot) emphasis teach about strength in service?" ] }, @@ -6598,9 +6590,7 @@ "analysis": "The consecration ram's blood applied to Aaron's right ear, thumb, and toe symbolizes that priests must hear God's word (ear), act on it (thumb/hand), and walk in it (toe/foot). Blood application sanctifies these members for holy service. Christ's blood sanctifies our hearing, working, and walking—our complete life consecrated through His atonement. The right side emphasizes the place of honor and strength.", "historical": "The blood application ceremony was unique to priestly consecration, marking the priests as blood-sanctified for service. This visible sign testified to their cleansing and separation for God's purposes.", "questions": [ - [ - "How does Christ's blood sanctify your hearing, working, and walking?" - ], + "How does Christ's blood sanctify your hearing, working, and walking?", "What does the 'right' (ear, hand, foot) emphasis teach about strength in service?" ] }, @@ -6608,9 +6598,7 @@ "analysis": "The consecration ram's blood applied to Aaron's right ear, thumb, and toe symbolizes that priests must hear God's word (ear), act on it (thumb/hand), and walk in it (toe/foot). Blood application sanctifies these members for holy service. Christ's blood sanctifies our hearing, working, and walking—our complete life consecrated through His atonement. The right side emphasizes the place of honor and strength.", "historical": "The blood application ceremony was unique to priestly consecration, marking the priests as blood-sanctified for service. This visible sign testified to their cleansing and separation for God's purposes.", "questions": [ - [ - "How does Christ's blood sanctify your hearing, working, and walking?" - ], + "How does Christ's blood sanctify your hearing, working, and walking?", "What does the 'right' (ear, hand, foot) emphasis teach about strength in service?" ] }, @@ -6618,9 +6606,7 @@ "analysis": "The consecration ram's blood applied to Aaron's right ear, thumb, and toe symbolizes that priests must hear God's word (ear), act on it (thumb/hand), and walk in it (toe/foot). Blood application sanctifies these members for holy service. Christ's blood sanctifies our hearing, working, and walking—our complete life consecrated through His atonement. The right side emphasizes the place of honor and strength.", "historical": "The blood application ceremony was unique to priestly consecration, marking the priests as blood-sanctified for service. This visible sign testified to their cleansing and separation for God's purposes.", "questions": [ - [ - "How does Christ's blood sanctify your hearing, working, and walking?" - ], + "How does Christ's blood sanctify your hearing, working, and walking?", "What does the 'right' (ear, hand, foot) emphasis teach about strength in service?" ] }, @@ -6628,9 +6614,7 @@ "analysis": "The consecration ram's blood applied to Aaron's right ear, thumb, and toe symbolizes that priests must hear God's word (ear), act on it (thumb/hand), and walk in it (toe/foot). Blood application sanctifies these members for holy service. Christ's blood sanctifies our hearing, working, and walking—our complete life consecrated through His atonement. The right side emphasizes the place of honor and strength.", "historical": "The blood application ceremony was unique to priestly consecration, marking the priests as blood-sanctified for service. This visible sign testified to their cleansing and separation for God's purposes.", "questions": [ - [ - "How does Christ's blood sanctify your hearing, working, and walking?" - ], + "How does Christ's blood sanctify your hearing, working, and walking?", "What does the 'right' (ear, hand, foot) emphasis teach about strength in service?" ] }, @@ -6638,9 +6622,7 @@ "analysis": "The consecration ram's blood applied to Aaron's right ear, thumb, and toe symbolizes that priests must hear God's word (ear), act on it (thumb/hand), and walk in it (toe/foot). Blood application sanctifies these members for holy service. Christ's blood sanctifies our hearing, working, and walking—our complete life consecrated through His atonement. The right side emphasizes the place of honor and strength.", "historical": "The blood application ceremony was unique to priestly consecration, marking the priests as blood-sanctified for service. This visible sign testified to their cleansing and separation for God's purposes.", "questions": [ - [ - "How does Christ's blood sanctify your hearing, working, and walking?" - ], + "How does Christ's blood sanctify your hearing, working, and walking?", "What does the 'right' (ear, hand, foot) emphasis teach about strength in service?" ] }, @@ -6648,9 +6630,7 @@ "analysis": "The consecration ram's blood applied to Aaron's right ear, thumb, and toe symbolizes that priests must hear God's word (ear), act on it (thumb/hand), and walk in it (toe/foot). Blood application sanctifies these members for holy service. Christ's blood sanctifies our hearing, working, and walking—our complete life consecrated through His atonement. The right side emphasizes the place of honor and strength.", "historical": "The blood application ceremony was unique to priestly consecration, marking the priests as blood-sanctified for service. This visible sign testified to their cleansing and separation for God's purposes.", "questions": [ - [ - "How does Christ's blood sanctify your hearing, working, and walking?" - ], + "How does Christ's blood sanctify your hearing, working, and walking?", "What does the 'right' (ear, hand, foot) emphasis teach about strength in service?" ] }, @@ -6658,9 +6638,7 @@ "analysis": "The seven-day consecration period represents complete, perfect preparation (seven = completeness). Aaron and his sons must remain at the tabernacle entrance throughout, unable to leave, fully devoted to consecration. This prefigures how believers, once called to Christ, must remain in Him continually—not part-time but full devotion. The daily repetition of sacrifices emphasizes that consecration requires ongoing renewal, ultimately fulfilled in Christ's once-for-all sacrifice.", "historical": "The seven-day period required priests to remain at the tabernacle entrance day and night, repeating sacrificial rituals daily. This intensive preparation demonstrated that priestly service demanded total commitment and thorough consecration.", "questions": [ - [ - "How does remaining 'at the tabernacle entrance' picture abiding in Christ?" - ], + "How does remaining 'at the tabernacle entrance' picture abiding in Christ?", "What does seven-day consecration teach about the completeness of preparation God requires?" ] }, @@ -6668,9 +6646,7 @@ "analysis": "The seven-day consecration period represents complete, perfect preparation (seven = completeness). Aaron and his sons must remain at the tabernacle entrance throughout, unable to leave, fully devoted to consecration. This prefigures how believers, once called to Christ, must remain in Him continually—not part-time but full devotion. The daily repetition of sacrifices emphasizes that consecration requires ongoing renewal, ultimately fulfilled in Christ's once-for-all sacrifice.", "historical": "The seven-day period required priests to remain at the tabernacle entrance day and night, repeating sacrificial rituals daily. This intensive preparation demonstrated that priestly service demanded total commitment and thorough consecration.", "questions": [ - [ - "How does remaining 'at the tabernacle entrance' picture abiding in Christ?" - ], + "How does remaining 'at the tabernacle entrance' picture abiding in Christ?", "What does seven-day consecration teach about the completeness of preparation God requires?" ] }, @@ -6678,9 +6654,7 @@ "analysis": "The seven-day consecration period represents complete, perfect preparation (seven = completeness). Aaron and his sons must remain at the tabernacle entrance throughout, unable to leave, fully devoted to consecration. This prefigures how believers, once called to Christ, must remain in Him continually—not part-time but full devotion. The daily repetition of sacrifices emphasizes that consecration requires ongoing renewal, ultimately fulfilled in Christ's once-for-all sacrifice.", "historical": "The seven-day period required priests to remain at the tabernacle entrance day and night, repeating sacrificial rituals daily. This intensive preparation demonstrated that priestly service demanded total commitment and thorough consecration.", "questions": [ - [ - "How does remaining 'at the tabernacle entrance' picture abiding in Christ?" - ], + "How does remaining 'at the tabernacle entrance' picture abiding in Christ?", "What does seven-day consecration teach about the completeness of preparation God requires?" ] }, @@ -6688,9 +6662,7 @@ "analysis": "The seven-day consecration period represents complete, perfect preparation (seven = completeness). Aaron and his sons must remain at the tabernacle entrance throughout, unable to leave, fully devoted to consecration. This prefigures how believers, once called to Christ, must remain in Him continually—not part-time but full devotion. The daily repetition of sacrifices emphasizes that consecration requires ongoing renewal, ultimately fulfilled in Christ's once-for-all sacrifice.", "historical": "The seven-day period required priests to remain at the tabernacle entrance day and night, repeating sacrificial rituals daily. This intensive preparation demonstrated that priestly service demanded total commitment and thorough consecration.", "questions": [ - [ - "How does remaining 'at the tabernacle entrance' picture abiding in Christ?" - ], + "How does remaining 'at the tabernacle entrance' picture abiding in Christ?", "What does seven-day consecration teach about the completeness of preparation God requires?" ] }, @@ -6698,9 +6670,7 @@ "analysis": "The seven-day consecration period represents complete, perfect preparation (seven = completeness). Aaron and his sons must remain at the tabernacle entrance throughout, unable to leave, fully devoted to consecration. This prefigures how believers, once called to Christ, must remain in Him continually—not part-time but full devotion. The daily repetition of sacrifices emphasizes that consecration requires ongoing renewal, ultimately fulfilled in Christ's once-for-all sacrifice.", "historical": "The seven-day period required priests to remain at the tabernacle entrance day and night, repeating sacrificial rituals daily. This intensive preparation demonstrated that priestly service demanded total commitment and thorough consecration.", "questions": [ - [ - "How does remaining 'at the tabernacle entrance' picture abiding in Christ?" - ], + "How does remaining 'at the tabernacle entrance' picture abiding in Christ?", "What does seven-day consecration teach about the completeness of preparation God requires?" ] }, @@ -6708,9 +6678,7 @@ "analysis": "The seven-day consecration period represents complete, perfect preparation (seven = completeness). Aaron and his sons must remain at the tabernacle entrance throughout, unable to leave, fully devoted to consecration. This prefigures how believers, once called to Christ, must remain in Him continually—not part-time but full devotion. The daily repetition of sacrifices emphasizes that consecration requires ongoing renewal, ultimately fulfilled in Christ's once-for-all sacrifice.", "historical": "The seven-day period required priests to remain at the tabernacle entrance day and night, repeating sacrificial rituals daily. This intensive preparation demonstrated that priestly service demanded total commitment and thorough consecration.", "questions": [ - [ - "How does remaining 'at the tabernacle entrance' picture abiding in Christ?" - ], + "How does remaining 'at the tabernacle entrance' picture abiding in Christ?", "What does seven-day consecration teach about the completeness of preparation God requires?" ] }, @@ -6718,9 +6686,7 @@ "analysis": "The seven-day consecration period represents complete, perfect preparation (seven = completeness). Aaron and his sons must remain at the tabernacle entrance throughout, unable to leave, fully devoted to consecration. This prefigures how believers, once called to Christ, must remain in Him continually—not part-time but full devotion. The daily repetition of sacrifices emphasizes that consecration requires ongoing renewal, ultimately fulfilled in Christ's once-for-all sacrifice.", "historical": "The seven-day period required priests to remain at the tabernacle entrance day and night, repeating sacrificial rituals daily. This intensive preparation demonstrated that priestly service demanded total commitment and thorough consecration.", "questions": [ - [ - "How does remaining 'at the tabernacle entrance' picture abiding in Christ?" - ], + "How does remaining 'at the tabernacle entrance' picture abiding in Christ?", "What does seven-day consecration teach about the completeness of preparation God requires?" ] }, @@ -6728,9 +6694,7 @@ "analysis": "God promises to dwell among Israel, meeting them at the tabernacle, His glory sanctifying the place and people. The daily offerings maintain covenant relationship—morning and evening, continually before the LORD. This perpetual worship prefigures Christ's eternal intercession and the New Covenant promise: 'I will be their God, and they shall be my people.' The tabernacle becomes the meeting place where God and man commune through prescribed atonement.", "historical": "The daily burnt offerings (morning and evening) continued throughout Israel's history, maintaining the covenant relationship established at Sinai. This perpetual worship demonstrated that relationship with God requires ongoing devotion, not one-time commitment.", "questions": [ - [ - "How does Christ's eternal intercession fulfill the 'daily offerings' pattern?" - ], + "How does Christ's eternal intercession fulfill the 'daily offerings' pattern?", "What does God's promise to 'dwell among you' mean for your daily life?" ] }, @@ -6738,9 +6702,7 @@ "analysis": "God promises to dwell among Israel, meeting them at the tabernacle, His glory sanctifying the place and people. The daily offerings maintain covenant relationship—morning and evening, continually before the LORD. This perpetual worship prefigures Christ's eternal intercession and the New Covenant promise: 'I will be their God, and they shall be my people.' The tabernacle becomes the meeting place where God and man commune through prescribed atonement.", "historical": "The daily burnt offerings (morning and evening) continued throughout Israel's history, maintaining the covenant relationship established at Sinai. This perpetual worship demonstrated that relationship with God requires ongoing devotion, not one-time commitment.", "questions": [ - [ - "How does Christ's eternal intercession fulfill the 'daily offerings' pattern?" - ], + "How does Christ's eternal intercession fulfill the 'daily offerings' pattern?", "What does God's promise to 'dwell among you' mean for your daily life?" ] }, @@ -6748,9 +6710,7 @@ "analysis": "God promises to dwell among Israel, meeting them at the tabernacle, His glory sanctifying the place and people. The daily offerings maintain covenant relationship—morning and evening, continually before the LORD. This perpetual worship prefigures Christ's eternal intercession and the New Covenant promise: 'I will be their God, and they shall be my people.' The tabernacle becomes the meeting place where God and man commune through prescribed atonement.", "historical": "The daily burnt offerings (morning and evening) continued throughout Israel's history, maintaining the covenant relationship established at Sinai. This perpetual worship demonstrated that relationship with God requires ongoing devotion, not one-time commitment.", "questions": [ - [ - "How does Christ's eternal intercession fulfill the 'daily offerings' pattern?" - ], + "How does Christ's eternal intercession fulfill the 'daily offerings' pattern?", "What does God's promise to 'dwell among you' mean for your daily life?" ] }, @@ -6758,9 +6718,7 @@ "analysis": "God promises to dwell among Israel, meeting them at the tabernacle, His glory sanctifying the place and people. The daily offerings maintain covenant relationship—morning and evening, continually before the LORD. This perpetual worship prefigures Christ's eternal intercession and the New Covenant promise: 'I will be their God, and they shall be my people.' The tabernacle becomes the meeting place where God and man commune through prescribed atonement.", "historical": "The daily burnt offerings (morning and evening) continued throughout Israel's history, maintaining the covenant relationship established at Sinai. This perpetual worship demonstrated that relationship with God requires ongoing devotion, not one-time commitment.", "questions": [ - [ - "How does Christ's eternal intercession fulfill the 'daily offerings' pattern?" - ], + "How does Christ's eternal intercession fulfill the 'daily offerings' pattern?", "What does God's promise to 'dwell among you' mean for your daily life?" ] }, @@ -6768,9 +6726,7 @@ "analysis": "God promises to dwell among Israel, meeting them at the tabernacle, His glory sanctifying the place and people. The daily offerings maintain covenant relationship—morning and evening, continually before the LORD. This perpetual worship prefigures Christ's eternal intercession and the New Covenant promise: 'I will be their God, and they shall be my people.' The tabernacle becomes the meeting place where God and man commune through prescribed atonement.", "historical": "The daily burnt offerings (morning and evening) continued throughout Israel's history, maintaining the covenant relationship established at Sinai. This perpetual worship demonstrated that relationship with God requires ongoing devotion, not one-time commitment.", "questions": [ - [ - "How does Christ's eternal intercession fulfill the 'daily offerings' pattern?" - ], + "How does Christ's eternal intercession fulfill the 'daily offerings' pattern?", "What does God's promise to 'dwell among you' mean for your daily life?" ] }, @@ -6778,9 +6734,7 @@ "analysis": "God promises to dwell among Israel, meeting them at the tabernacle, His glory sanctifying the place and people. The daily offerings maintain covenant relationship—morning and evening, continually before the LORD. This perpetual worship prefigures Christ's eternal intercession and the New Covenant promise: 'I will be their God, and they shall be my people.' The tabernacle becomes the meeting place where God and man commune through prescribed atonement.", "historical": "The daily burnt offerings (morning and evening) continued throughout Israel's history, maintaining the covenant relationship established at Sinai. This perpetual worship demonstrated that relationship with God requires ongoing devotion, not one-time commitment.", "questions": [ - [ - "How does Christ's eternal intercession fulfill the 'daily offerings' pattern?" - ], + "How does Christ's eternal intercession fulfill the 'daily offerings' pattern?", "What does God's promise to 'dwell among you' mean for your daily life?" ] }, @@ -6788,9 +6742,7 @@ "analysis": "God promises to dwell among Israel, meeting them at the tabernacle, His glory sanctifying the place and people. The daily offerings maintain covenant relationship—morning and evening, continually before the LORD. This perpetual worship prefigures Christ's eternal intercession and the New Covenant promise: 'I will be their God, and they shall be my people.' The tabernacle becomes the meeting place where God and man commune through prescribed atonement.", "historical": "The daily burnt offerings (morning and evening) continued throughout Israel's history, maintaining the covenant relationship established at Sinai. This perpetual worship demonstrated that relationship with God requires ongoing devotion, not one-time commitment.", "questions": [ - [ - "How does Christ's eternal intercession fulfill the 'daily offerings' pattern?" - ], + "How does Christ's eternal intercession fulfill the 'daily offerings' pattern?", "What does God's promise to 'dwell among you' mean for your daily life?" ] }, @@ -6798,9 +6750,7 @@ "analysis": "God promises to dwell among Israel, meeting them at the tabernacle, His glory sanctifying the place and people. The daily offerings maintain covenant relationship—morning and evening, continually before the LORD. This perpetual worship prefigures Christ's eternal intercession and the New Covenant promise: 'I will be their God, and they shall be my people.' The tabernacle becomes the meeting place where God and man commune through prescribed atonement.", "historical": "The daily burnt offerings (morning and evening) continued throughout Israel's history, maintaining the covenant relationship established at Sinai. This perpetual worship demonstrated that relationship with God requires ongoing devotion, not one-time commitment.", "questions": [ - [ - "How does Christ's eternal intercession fulfill the 'daily offerings' pattern?" - ], + "How does Christ's eternal intercession fulfill the 'daily offerings' pattern?", "What does God's promise to 'dwell among you' mean for your daily life?" ] }, @@ -6808,9 +6758,7 @@ "analysis": "God promises to dwell among Israel, meeting them at the tabernacle, His glory sanctifying the place and people. The daily offerings maintain covenant relationship—morning and evening, continually before the LORD. This perpetual worship prefigures Christ's eternal intercession and the New Covenant promise: 'I will be their God, and they shall be my people.' The tabernacle becomes the meeting place where God and man commune through prescribed atonement.", "historical": "The daily burnt offerings (morning and evening) continued throughout Israel's history, maintaining the covenant relationship established at Sinai. This perpetual worship demonstrated that relationship with God requires ongoing devotion, not one-time commitment.", "questions": [ - [ - "How does Christ's eternal intercession fulfill the 'daily offerings' pattern?" - ], + "How does Christ's eternal intercession fulfill the 'daily offerings' pattern?", "What does God's promise to 'dwell among you' mean for your daily life?" ] }, @@ -6818,9 +6766,7 @@ "analysis": "God promises to dwell among Israel, meeting them at the tabernacle, His glory sanctifying the place and people. The daily offerings maintain covenant relationship—morning and evening, continually before the LORD. This perpetual worship prefigures Christ's eternal intercession and the New Covenant promise: 'I will be their God, and they shall be my people.' The tabernacle becomes the meeting place where God and man commune through prescribed atonement.", "historical": "The daily burnt offerings (morning and evening) continued throughout Israel's history, maintaining the covenant relationship established at Sinai. This perpetual worship demonstrated that relationship with God requires ongoing devotion, not one-time commitment.", "questions": [ - [ - "How does Christ's eternal intercession fulfill the 'daily offerings' pattern?" - ], + "How does Christ's eternal intercession fulfill the 'daily offerings' pattern?", "What does God's promise to 'dwell among you' mean for your daily life?" ] }, @@ -6828,9 +6774,7 @@ "analysis": "God promises to dwell among Israel, meeting them at the tabernacle, His glory sanctifying the place and people. The daily offerings maintain covenant relationship—morning and evening, continually before the LORD. This perpetual worship prefigures Christ's eternal intercession and the New Covenant promise: 'I will be their God, and they shall be my people.' The tabernacle becomes the meeting place where God and man commune through prescribed atonement.", "historical": "The daily burnt offerings (morning and evening) continued throughout Israel's history, maintaining the covenant relationship established at Sinai. This perpetual worship demonstrated that relationship with God requires ongoing devotion, not one-time commitment.", "questions": [ - [ - "How does Christ's eternal intercession fulfill the 'daily offerings' pattern?" - ], + "How does Christ's eternal intercession fulfill the 'daily offerings' pattern?", "What does God's promise to 'dwell among you' mean for your daily life?" ] } @@ -6920,9 +6864,7 @@ "analysis": "The half-shekel atonement money (ransom for souls) demonstrates that all are equally valued before God—rich and poor pay the same. No one can pay more or less for their soul; redemption has fixed price. This prefigures how Christ's atonement has equal value for all—not more for the worthy, not less for the unworthy. The silver (redemption metal) collected supported tabernacle service, showing that redeemed people fund God's ongoing work.", "historical": "The half-shekel (approximately 0.2 ounces of silver) was collected during census-taking, serving both as atonement money and practical support for the tabernacle. This became an annual temple tax in later periods.", "questions": [ - [ - "What does equal payment (rich and poor) teach about the equality of Christ's redemption?" - ], + "What does equal payment (rich and poor) teach about the equality of Christ's redemption?", "How do redeemed people support God's ongoing work in the world?" ] }, @@ -6930,9 +6872,7 @@ "analysis": "The half-shekel atonement money (ransom for souls) demonstrates that all are equally valued before God—rich and poor pay the same. No one can pay more or less for their soul; redemption has fixed price. This prefigures how Christ's atonement has equal value for all—not more for the worthy, not less for the unworthy. The silver (redemption metal) collected supported tabernacle service, showing that redeemed people fund God's ongoing work.", "historical": "The half-shekel (approximately 0.2 ounces of silver) was collected during census-taking, serving both as atonement money and practical support for the tabernacle. This became an annual temple tax in later periods.", "questions": [ - [ - "What does equal payment (rich and poor) teach about the equality of Christ's redemption?" - ], + "What does equal payment (rich and poor) teach about the equality of Christ's redemption?", "How do redeemed people support God's ongoing work in the world?" ] }, @@ -6940,9 +6880,7 @@ "analysis": "The half-shekel atonement money (ransom for souls) demonstrates that all are equally valued before God—rich and poor pay the same. No one can pay more or less for their soul; redemption has fixed price. This prefigures how Christ's atonement has equal value for all—not more for the worthy, not less for the unworthy. The silver (redemption metal) collected supported tabernacle service, showing that redeemed people fund God's ongoing work.", "historical": "The half-shekel (approximately 0.2 ounces of silver) was collected during census-taking, serving both as atonement money and practical support for the tabernacle. This became an annual temple tax in later periods.", "questions": [ - [ - "What does equal payment (rich and poor) teach about the equality of Christ's redemption?" - ], + "What does equal payment (rich and poor) teach about the equality of Christ's redemption?", "How do redeemed people support God's ongoing work in the world?" ] }, @@ -6950,9 +6888,7 @@ "analysis": "The half-shekel atonement money (ransom for souls) demonstrates that all are equally valued before God—rich and poor pay the same. No one can pay more or less for their soul; redemption has fixed price. This prefigures how Christ's atonement has equal value for all—not more for the worthy, not less for the unworthy. The silver (redemption metal) collected supported tabernacle service, showing that redeemed people fund God's ongoing work.", "historical": "The half-shekel (approximately 0.2 ounces of silver) was collected during census-taking, serving both as atonement money and practical support for the tabernacle. This became an annual temple tax in later periods.", "questions": [ - [ - "What does equal payment (rich and poor) teach about the equality of Christ's redemption?" - ], + "What does equal payment (rich and poor) teach about the equality of Christ's redemption?", "How do redeemed people support God's ongoing work in the world?" ] }, @@ -6960,9 +6896,7 @@ "analysis": "The half-shekel atonement money (ransom for souls) demonstrates that all are equally valued before God—rich and poor pay the same. No one can pay more or less for their soul; redemption has fixed price. This prefigures how Christ's atonement has equal value for all—not more for the worthy, not less for the unworthy. The silver (redemption metal) collected supported tabernacle service, showing that redeemed people fund God's ongoing work.", "historical": "The half-shekel (approximately 0.2 ounces of silver) was collected during census-taking, serving both as atonement money and practical support for the tabernacle. This became an annual temple tax in later periods.", "questions": [ - [ - "What does equal payment (rich and poor) teach about the equality of Christ's redemption?" - ], + "What does equal payment (rich and poor) teach about the equality of Christ's redemption?", "How do redeemed people support God's ongoing work in the world?" ] }, @@ -6970,9 +6904,7 @@ "analysis": "The half-shekel atonement money (ransom for souls) demonstrates that all are equally valued before God—rich and poor pay the same. No one can pay more or less for their soul; redemption has fixed price. This prefigures how Christ's atonement has equal value for all—not more for the worthy, not less for the unworthy. The silver (redemption metal) collected supported tabernacle service, showing that redeemed people fund God's ongoing work.", "historical": "The half-shekel (approximately 0.2 ounces of silver) was collected during census-taking, serving both as atonement money and practical support for the tabernacle. This became an annual temple tax in later periods.", "questions": [ - [ - "What does equal payment (rich and poor) teach about the equality of Christ's redemption?" - ], + "What does equal payment (rich and poor) teach about the equality of Christ's redemption?", "How do redeemed people support God's ongoing work in the world?" ] }, @@ -6980,9 +6912,7 @@ "analysis": "The bronze laver for washing hands and feet represents ongoing sanctification—priests must wash before serving or die. Initial consecration washing (ch 29) cleansed once; laver washing cleanses continually for service. This prefigures the difference between justification (initial cleansing) and sanctification (ongoing cleansing). Christ provides both—His blood justifies once for all; His word sanctifies daily (John 13:10, 15:3, Ephesians 5:26).", "historical": "The bronze laver stood between the altar and tabernacle entrance, reminding priests that service requires both sacrifice and cleansing. The bronze construction (from women's mirrors, Exodus 38:8) symbolized judgment/self-examination.", "questions": [ - [ - "How does Christ provide both initial cleansing (justification) and daily cleansing (sanctification)?" - ], + "How does Christ provide both initial cleansing (justification) and daily cleansing (sanctification)?", "What 'hands and feet' (work and walk) need daily washing in your life?" ] }, @@ -6990,9 +6920,7 @@ "analysis": "The bronze laver for washing hands and feet represents ongoing sanctification—priests must wash before serving or die. Initial consecration washing (ch 29) cleansed once; laver washing cleanses continually for service. This prefigures the difference between justification (initial cleansing) and sanctification (ongoing cleansing). Christ provides both—His blood justifies once for all; His word sanctifies daily (John 13:10, 15:3, Ephesians 5:26).", "historical": "The bronze laver stood between the altar and tabernacle entrance, reminding priests that service requires both sacrifice and cleansing. The bronze construction (from women's mirrors, Exodus 38:8) symbolized judgment/self-examination.", "questions": [ - [ - "How does Christ provide both initial cleansing (justification) and daily cleansing (sanctification)?" - ], + "How does Christ provide both initial cleansing (justification) and daily cleansing (sanctification)?", "What 'hands and feet' (work and walk) need daily washing in your life?" ] }, @@ -7000,9 +6928,7 @@ "analysis": "The bronze laver for washing hands and feet represents ongoing sanctification—priests must wash before serving or die. Initial consecration washing (ch 29) cleansed once; laver washing cleanses continually for service. This prefigures the difference between justification (initial cleansing) and sanctification (ongoing cleansing). Christ provides both—His blood justifies once for all; His word sanctifies daily (John 13:10, 15:3, Ephesians 5:26).", "historical": "The bronze laver stood between the altar and tabernacle entrance, reminding priests that service requires both sacrifice and cleansing. The bronze construction (from women's mirrors, Exodus 38:8) symbolized judgment/self-examination.", "questions": [ - [ - "How does Christ provide both initial cleansing (justification) and daily cleansing (sanctification)?" - ], + "How does Christ provide both initial cleansing (justification) and daily cleansing (sanctification)?", "What 'hands and feet' (work and walk) need daily washing in your life?" ] }, @@ -7010,9 +6936,7 @@ "analysis": "The bronze laver for washing hands and feet represents ongoing sanctification—priests must wash before serving or die. Initial consecration washing (ch 29) cleansed once; laver washing cleanses continually for service. This prefigures the difference between justification (initial cleansing) and sanctification (ongoing cleansing). Christ provides both—His blood justifies once for all; His word sanctifies daily (John 13:10, 15:3, Ephesians 5:26).", "historical": "The bronze laver stood between the altar and tabernacle entrance, reminding priests that service requires both sacrifice and cleansing. The bronze construction (from women's mirrors, Exodus 38:8) symbolized judgment/self-examination.", "questions": [ - [ - "How does Christ provide both initial cleansing (justification) and daily cleansing (sanctification)?" - ], + "How does Christ provide both initial cleansing (justification) and daily cleansing (sanctification)?", "What 'hands and feet' (work and walk) need daily washing in your life?" ] }, @@ -7020,9 +6944,7 @@ "analysis": "The bronze laver for washing hands and feet represents ongoing sanctification—priests must wash before serving or die. Initial consecration washing (ch 29) cleansed once; laver washing cleanses continually for service. This prefigures the difference between justification (initial cleansing) and sanctification (ongoing cleansing). Christ provides both—His blood justifies once for all; His word sanctifies daily (John 13:10, 15:3, Ephesians 5:26).", "historical": "The bronze laver stood between the altar and tabernacle entrance, reminding priests that service requires both sacrifice and cleansing. The bronze construction (from women's mirrors, Exodus 38:8) symbolized judgment/self-examination.", "questions": [ - [ - "How does Christ provide both initial cleansing (justification) and daily cleansing (sanctification)?" - ], + "How does Christ provide both initial cleansing (justification) and daily cleansing (sanctification)?", "What 'hands and feet' (work and walk) need daily washing in your life?" ] }, @@ -7030,9 +6952,7 @@ "analysis": "The sacred anointing oil—myrrh, cinnamon, calamus, cassia in olive oil—represents the Holy Spirit's multifaceted work. Each spice contributes unique fragrance, together creating complete anointing. The oil's holiness (never for common use) emphasizes that the Spirit is sacred, not to be counterfeited or treated casually. Christ was anointed with this spiritual reality, receiving the Spirit without measure (John 3:34). Believers receive the same Spirit, though in measure.", "historical": "The specific spice formula was divinely prescribed and forbidden for common use—counterfeit anointing oil incurred severe penalty. This protected the sacred symbolism and prevented profaning what represented God's Spirit.", "questions": [ - [ - "How does each spice's unique contribution illustrate the Holy Spirit's multifaceted work?" - ], + "How does each spice's unique contribution illustrate the Holy Spirit's multifaceted work?", "What does the oil's sacred exclusivity teach about treating the Holy Spirit with reverence?" ] }, @@ -7040,9 +6960,7 @@ "analysis": "The sacred anointing oil—myrrh, cinnamon, calamus, cassia in olive oil—represents the Holy Spirit's multifaceted work. Each spice contributes unique fragrance, together creating complete anointing. The oil's holiness (never for common use) emphasizes that the Spirit is sacred, not to be counterfeited or treated casually. Christ was anointed with this spiritual reality, receiving the Spirit without measure (John 3:34). Believers receive the same Spirit, though in measure.", "historical": "The specific spice formula was divinely prescribed and forbidden for common use—counterfeit anointing oil incurred severe penalty. This protected the sacred symbolism and prevented profaning what represented God's Spirit.", "questions": [ - [ - "How does each spice's unique contribution illustrate the Holy Spirit's multifaceted work?" - ], + "How does each spice's unique contribution illustrate the Holy Spirit's multifaceted work?", "What does the oil's sacred exclusivity teach about treating the Holy Spirit with reverence?" ] }, @@ -7050,9 +6968,7 @@ "analysis": "The sacred anointing oil—myrrh, cinnamon, calamus, cassia in olive oil—represents the Holy Spirit's multifaceted work. Each spice contributes unique fragrance, together creating complete anointing. The oil's holiness (never for common use) emphasizes that the Spirit is sacred, not to be counterfeited or treated casually. Christ was anointed with this spiritual reality, receiving the Spirit without measure (John 3:34). Believers receive the same Spirit, though in measure.", "historical": "The specific spice formula was divinely prescribed and forbidden for common use—counterfeit anointing oil incurred severe penalty. This protected the sacred symbolism and prevented profaning what represented God's Spirit.", "questions": [ - [ - "How does each spice's unique contribution illustrate the Holy Spirit's multifaceted work?" - ], + "How does each spice's unique contribution illustrate the Holy Spirit's multifaceted work?", "What does the oil's sacred exclusivity teach about treating the Holy Spirit with reverence?" ] }, @@ -7060,9 +6976,7 @@ "analysis": "The sacred anointing oil—myrrh, cinnamon, calamus, cassia in olive oil—represents the Holy Spirit's multifaceted work. Each spice contributes unique fragrance, together creating complete anointing. The oil's holiness (never for common use) emphasizes that the Spirit is sacred, not to be counterfeited or treated casually. Christ was anointed with this spiritual reality, receiving the Spirit without measure (John 3:34). Believers receive the same Spirit, though in measure.", "historical": "The specific spice formula was divinely prescribed and forbidden for common use—counterfeit anointing oil incurred severe penalty. This protected the sacred symbolism and prevented profaning what represented God's Spirit.", "questions": [ - [ - "How does each spice's unique contribution illustrate the Holy Spirit's multifaceted work?" - ], + "How does each spice's unique contribution illustrate the Holy Spirit's multifaceted work?", "What does the oil's sacred exclusivity teach about treating the Holy Spirit with reverence?" ] }, @@ -7070,9 +6984,7 @@ "analysis": "The sacred anointing oil—myrrh, cinnamon, calamus, cassia in olive oil—represents the Holy Spirit's multifaceted work. Each spice contributes unique fragrance, together creating complete anointing. The oil's holiness (never for common use) emphasizes that the Spirit is sacred, not to be counterfeited or treated casually. Christ was anointed with this spiritual reality, receiving the Spirit without measure (John 3:34). Believers receive the same Spirit, though in measure.", "historical": "The specific spice formula was divinely prescribed and forbidden for common use—counterfeit anointing oil incurred severe penalty. This protected the sacred symbolism and prevented profaning what represented God's Spirit.", "questions": [ - [ - "How does each spice's unique contribution illustrate the Holy Spirit's multifaceted work?" - ], + "How does each spice's unique contribution illustrate the Holy Spirit's multifaceted work?", "What does the oil's sacred exclusivity teach about treating the Holy Spirit with reverence?" ] }, @@ -7080,9 +6992,7 @@ "analysis": "The sacred anointing oil—myrrh, cinnamon, calamus, cassia in olive oil—represents the Holy Spirit's multifaceted work. Each spice contributes unique fragrance, together creating complete anointing. The oil's holiness (never for common use) emphasizes that the Spirit is sacred, not to be counterfeited or treated casually. Christ was anointed with this spiritual reality, receiving the Spirit without measure (John 3:34). Believers receive the same Spirit, though in measure.", "historical": "The specific spice formula was divinely prescribed and forbidden for common use—counterfeit anointing oil incurred severe penalty. This protected the sacred symbolism and prevented profaning what represented God's Spirit.", "questions": [ - [ - "How does each spice's unique contribution illustrate the Holy Spirit's multifaceted work?" - ], + "How does each spice's unique contribution illustrate the Holy Spirit's multifaceted work?", "What does the oil's sacred exclusivity teach about treating the Holy Spirit with reverence?" ] }, @@ -7090,9 +7000,7 @@ "analysis": "The sacred anointing oil—myrrh, cinnamon, calamus, cassia in olive oil—represents the Holy Spirit's multifaceted work. Each spice contributes unique fragrance, together creating complete anointing. The oil's holiness (never for common use) emphasizes that the Spirit is sacred, not to be counterfeited or treated casually. Christ was anointed with this spiritual reality, receiving the Spirit without measure (John 3:34). Believers receive the same Spirit, though in measure.", "historical": "The specific spice formula was divinely prescribed and forbidden for common use—counterfeit anointing oil incurred severe penalty. This protected the sacred symbolism and prevented profaning what represented God's Spirit.", "questions": [ - [ - "How does each spice's unique contribution illustrate the Holy Spirit's multifaceted work?" - ], + "How does each spice's unique contribution illustrate the Holy Spirit's multifaceted work?", "What does the oil's sacred exclusivity teach about treating the Holy Spirit with reverence?" ] }, @@ -7100,9 +7008,7 @@ "analysis": "The sacred anointing oil—myrrh, cinnamon, calamus, cassia in olive oil—represents the Holy Spirit's multifaceted work. Each spice contributes unique fragrance, together creating complete anointing. The oil's holiness (never for common use) emphasizes that the Spirit is sacred, not to be counterfeited or treated casually. Christ was anointed with this spiritual reality, receiving the Spirit without measure (John 3:34). Believers receive the same Spirit, though in measure.", "historical": "The specific spice formula was divinely prescribed and forbidden for common use—counterfeit anointing oil incurred severe penalty. This protected the sacred symbolism and prevented profaning what represented God's Spirit.", "questions": [ - [ - "How does each spice's unique contribution illustrate the Holy Spirit's multifaceted work?" - ], + "How does each spice's unique contribution illustrate the Holy Spirit's multifaceted work?", "What does the oil's sacred exclusivity teach about treating the Holy Spirit with reverence?" ] }, @@ -7110,9 +7016,7 @@ "analysis": "The sacred anointing oil—myrrh, cinnamon, calamus, cassia in olive oil—represents the Holy Spirit's multifaceted work. Each spice contributes unique fragrance, together creating complete anointing. The oil's holiness (never for common use) emphasizes that the Spirit is sacred, not to be counterfeited or treated casually. Christ was anointed with this spiritual reality, receiving the Spirit without measure (John 3:34). Believers receive the same Spirit, though in measure.", "historical": "The specific spice formula was divinely prescribed and forbidden for common use—counterfeit anointing oil incurred severe penalty. This protected the sacred symbolism and prevented profaning what represented God's Spirit.", "questions": [ - [ - "How does each spice's unique contribution illustrate the Holy Spirit's multifaceted work?" - ], + "How does each spice's unique contribution illustrate the Holy Spirit's multifaceted work?", "What does the oil's sacred exclusivity teach about treating the Holy Spirit with reverence?" ] }, @@ -7120,9 +7024,7 @@ "analysis": "The sacred anointing oil—myrrh, cinnamon, calamus, cassia in olive oil—represents the Holy Spirit's multifaceted work. Each spice contributes unique fragrance, together creating complete anointing. The oil's holiness (never for common use) emphasizes that the Spirit is sacred, not to be counterfeited or treated casually. Christ was anointed with this spiritual reality, receiving the Spirit without measure (John 3:34). Believers receive the same Spirit, though in measure.", "historical": "The specific spice formula was divinely prescribed and forbidden for common use—counterfeit anointing oil incurred severe penalty. This protected the sacred symbolism and prevented profaning what represented God's Spirit.", "questions": [ - [ - "How does each spice's unique contribution illustrate the Holy Spirit's multifaceted work?" - ], + "How does each spice's unique contribution illustrate the Holy Spirit's multifaceted work?", "What does the oil's sacred exclusivity teach about treating the Holy Spirit with reverence?" ] }, @@ -7130,9 +7032,7 @@ "analysis": "The sacred anointing oil—myrrh, cinnamon, calamus, cassia in olive oil—represents the Holy Spirit's multifaceted work. Each spice contributes unique fragrance, together creating complete anointing. The oil's holiness (never for common use) emphasizes that the Spirit is sacred, not to be counterfeited or treated casually. Christ was anointed with this spiritual reality, receiving the Spirit without measure (John 3:34). Believers receive the same Spirit, though in measure.", "historical": "The specific spice formula was divinely prescribed and forbidden for common use—counterfeit anointing oil incurred severe penalty. This protected the sacred symbolism and prevented profaning what represented God's Spirit.", "questions": [ - [ - "How does each spice's unique contribution illustrate the Holy Spirit's multifaceted work?" - ], + "How does each spice's unique contribution illustrate the Holy Spirit's multifaceted work?", "What does the oil's sacred exclusivity teach about treating the Holy Spirit with reverence?" ] }, @@ -7140,9 +7040,7 @@ "analysis": "The sacred anointing oil—myrrh, cinnamon, calamus, cassia in olive oil—represents the Holy Spirit's multifaceted work. Each spice contributes unique fragrance, together creating complete anointing. The oil's holiness (never for common use) emphasizes that the Spirit is sacred, not to be counterfeited or treated casually. Christ was anointed with this spiritual reality, receiving the Spirit without measure (John 3:34). Believers receive the same Spirit, though in measure.", "historical": "The specific spice formula was divinely prescribed and forbidden for common use—counterfeit anointing oil incurred severe penalty. This protected the sacred symbolism and prevented profaning what represented God's Spirit.", "questions": [ - [ - "How does each spice's unique contribution illustrate the Holy Spirit's multifaceted work?" - ], + "How does each spice's unique contribution illustrate the Holy Spirit's multifaceted work?", "What does the oil's sacred exclusivity teach about treating the Holy Spirit with reverence?" ] }, @@ -7150,9 +7048,7 @@ "analysis": "The holy incense formula—stacte, onycha, galbanum, frankincense—represents acceptable prayer. Like the anointing oil, this formula was sacred, forbidden for common use. The specific ingredients create a fragrance pleasing to God, teaching that prayer must be according to God's will to be acceptable. Christ's intercession is the perfect incense; our prayers, offered through Him, become fragrant to God (2 Corinthians 2:15).", "historical": "The incense burned twice daily on the golden altar, filling the Holy Place with fragrant smoke. Offering strange/unauthorized incense resulted in death (Leviticus 10:1-2), emphasizing that worship must follow God's prescription.", "questions": [ - [ - "How does Christ's intercession serve as 'perfect incense' making your prayers acceptable?" - ], + "How does Christ's intercession serve as 'perfect incense' making your prayers acceptable?", "What does the forbidden counterfeiting teach about worshiping according to God's pattern?" ] }, @@ -7160,9 +7056,7 @@ "analysis": "The holy incense formula—stacte, onycha, galbanum, frankincense—represents acceptable prayer. Like the anointing oil, this formula was sacred, forbidden for common use. The specific ingredients create a fragrance pleasing to God, teaching that prayer must be according to God's will to be acceptable. Christ's intercession is the perfect incense; our prayers, offered through Him, become fragrant to God (2 Corinthians 2:15).", "historical": "The incense burned twice daily on the golden altar, filling the Holy Place with fragrant smoke. Offering strange/unauthorized incense resulted in death (Leviticus 10:1-2), emphasizing that worship must follow God's prescription.", "questions": [ - [ - "How does Christ's intercession serve as 'perfect incense' making your prayers acceptable?" - ], + "How does Christ's intercession serve as 'perfect incense' making your prayers acceptable?", "What does the forbidden counterfeiting teach about worshiping according to God's pattern?" ] }, @@ -7170,9 +7064,7 @@ "analysis": "The holy incense formula—stacte, onycha, galbanum, frankincense—represents acceptable prayer. Like the anointing oil, this formula was sacred, forbidden for common use. The specific ingredients create a fragrance pleasing to God, teaching that prayer must be according to God's will to be acceptable. Christ's intercession is the perfect incense; our prayers, offered through Him, become fragrant to God (2 Corinthians 2:15).", "historical": "The incense burned twice daily on the golden altar, filling the Holy Place with fragrant smoke. Offering strange/unauthorized incense resulted in death (Leviticus 10:1-2), emphasizing that worship must follow God's prescription.", "questions": [ - [ - "How does Christ's intercession serve as 'perfect incense' making your prayers acceptable?" - ], + "How does Christ's intercession serve as 'perfect incense' making your prayers acceptable?", "What does the forbidden counterfeiting teach about worshiping according to God's pattern?" ] }, @@ -7180,9 +7072,7 @@ "analysis": "The holy incense formula—stacte, onycha, galbanum, frankincense—represents acceptable prayer. Like the anointing oil, this formula was sacred, forbidden for common use. The specific ingredients create a fragrance pleasing to God, teaching that prayer must be according to God's will to be acceptable. Christ's intercession is the perfect incense; our prayers, offered through Him, become fragrant to God (2 Corinthians 2:15).", "historical": "The incense burned twice daily on the golden altar, filling the Holy Place with fragrant smoke. Offering strange/unauthorized incense resulted in death (Leviticus 10:1-2), emphasizing that worship must follow God's prescription.", "questions": [ - [ - "How does Christ's intercession serve as 'perfect incense' making your prayers acceptable?" - ], + "How does Christ's intercession serve as 'perfect incense' making your prayers acceptable?", "What does the forbidden counterfeiting teach about worshiping according to God's pattern?" ] }, @@ -7190,9 +7080,7 @@ "analysis": "The holy incense formula—stacte, onycha, galbanum, frankincense—represents acceptable prayer. Like the anointing oil, this formula was sacred, forbidden for common use. The specific ingredients create a fragrance pleasing to God, teaching that prayer must be according to God's will to be acceptable. Christ's intercession is the perfect incense; our prayers, offered through Him, become fragrant to God (2 Corinthians 2:15).", "historical": "The incense burned twice daily on the golden altar, filling the Holy Place with fragrant smoke. Offering strange/unauthorized incense resulted in death (Leviticus 10:1-2), emphasizing that worship must follow God's prescription.", "questions": [ - [ - "How does Christ's intercession serve as 'perfect incense' making your prayers acceptable?" - ], + "How does Christ's intercession serve as 'perfect incense' making your prayers acceptable?", "What does the forbidden counterfeiting teach about worshiping according to God's pattern?" ] } @@ -7218,9 +7106,7 @@ "analysis": "Bezalel and Oholiab are filled with God's Spirit for artistic work—wisdom, understanding, knowledge, craftsmanship. This demonstrates that the Holy Spirit equips not only for preaching/teaching but for creative, technical skills. All talents serve God's purposes when consecrated to Him. The Spirit who designed creation enables artisans to create beauty for worship. Christ, the wisdom of God, is the ultimate craftsman who builds His church.", "historical": "These craftsmen led teams of skilled workers who constructed the tabernacle according to Moses' pattern. Their Spirit-filling for technical work demonstrated that God values and empowers all forms of service, not just spiritual leadership.", "questions": [ - [ - "How does the Spirit's equipping for artistic work validate creativity and craftsmanship as ministry?" - ], + "How does the Spirit's equipping for artistic work validate creativity and craftsmanship as ministry?", "What talents has God given you that can serve His purposes when consecrated to Him?" ] }, @@ -7228,9 +7114,7 @@ "analysis": "Bezalel and Oholiab are filled with God's Spirit for artistic work—wisdom, understanding, knowledge, craftsmanship. This demonstrates that the Holy Spirit equips not only for preaching/teaching but for creative, technical skills. All talents serve God's purposes when consecrated to Him. The Spirit who designed creation enables artisans to create beauty for worship. Christ, the wisdom of God, is the ultimate craftsman who builds His church.", "historical": "These craftsmen led teams of skilled workers who constructed the tabernacle according to Moses' pattern. Their Spirit-filling for technical work demonstrated that God values and empowers all forms of service, not just spiritual leadership.", "questions": [ - [ - "How does the Spirit's equipping for artistic work validate creativity and craftsmanship as ministry?" - ], + "How does the Spirit's equipping for artistic work validate creativity and craftsmanship as ministry?", "What talents has God given you that can serve His purposes when consecrated to Him?" ] }, @@ -7238,9 +7122,7 @@ "analysis": "Bezalel and Oholiab are filled with God's Spirit for artistic work—wisdom, understanding, knowledge, craftsmanship. This demonstrates that the Holy Spirit equips not only for preaching/teaching but for creative, technical skills. All talents serve God's purposes when consecrated to Him. The Spirit who designed creation enables artisans to create beauty for worship. Christ, the wisdom of God, is the ultimate craftsman who builds His church.", "historical": "These craftsmen led teams of skilled workers who constructed the tabernacle according to Moses' pattern. Their Spirit-filling for technical work demonstrated that God values and empowers all forms of service, not just spiritual leadership.", "questions": [ - [ - "How does the Spirit's equipping for artistic work validate creativity and craftsmanship as ministry?" - ], + "How does the Spirit's equipping for artistic work validate creativity and craftsmanship as ministry?", "What talents has God given you that can serve His purposes when consecrated to Him?" ] }, @@ -7248,9 +7130,7 @@ "analysis": "Bezalel and Oholiab are filled with God's Spirit for artistic work—wisdom, understanding, knowledge, craftsmanship. This demonstrates that the Holy Spirit equips not only for preaching/teaching but for creative, technical skills. All talents serve God's purposes when consecrated to Him. The Spirit who designed creation enables artisans to create beauty for worship. Christ, the wisdom of God, is the ultimate craftsman who builds His church.", "historical": "These craftsmen led teams of skilled workers who constructed the tabernacle according to Moses' pattern. Their Spirit-filling for technical work demonstrated that God values and empowers all forms of service, not just spiritual leadership.", "questions": [ - [ - "How does the Spirit's equipping for artistic work validate creativity and craftsmanship as ministry?" - ], + "How does the Spirit's equipping for artistic work validate creativity and craftsmanship as ministry?", "What talents has God given you that can serve His purposes when consecrated to Him?" ] }, @@ -7258,9 +7138,7 @@ "analysis": "Bezalel and Oholiab are filled with God's Spirit for artistic work—wisdom, understanding, knowledge, craftsmanship. This demonstrates that the Holy Spirit equips not only for preaching/teaching but for creative, technical skills. All talents serve God's purposes when consecrated to Him. The Spirit who designed creation enables artisans to create beauty for worship. Christ, the wisdom of God, is the ultimate craftsman who builds His church.", "historical": "These craftsmen led teams of skilled workers who constructed the tabernacle according to Moses' pattern. Their Spirit-filling for technical work demonstrated that God values and empowers all forms of service, not just spiritual leadership.", "questions": [ - [ - "How does the Spirit's equipping for artistic work validate creativity and craftsmanship as ministry?" - ], + "How does the Spirit's equipping for artistic work validate creativity and craftsmanship as ministry?", "What talents has God given you that can serve His purposes when consecrated to Him?" ] }, @@ -7268,9 +7146,7 @@ "analysis": "Bezalel and Oholiab are filled with God's Spirit for artistic work—wisdom, understanding, knowledge, craftsmanship. This demonstrates that the Holy Spirit equips not only for preaching/teaching but for creative, technical skills. All talents serve God's purposes when consecrated to Him. The Spirit who designed creation enables artisans to create beauty for worship. Christ, the wisdom of God, is the ultimate craftsman who builds His church.", "historical": "These craftsmen led teams of skilled workers who constructed the tabernacle according to Moses' pattern. Their Spirit-filling for technical work demonstrated that God values and empowers all forms of service, not just spiritual leadership.", "questions": [ - [ - "How does the Spirit's equipping for artistic work validate creativity and craftsmanship as ministry?" - ], + "How does the Spirit's equipping for artistic work validate creativity and craftsmanship as ministry?", "What talents has God given you that can serve His purposes when consecrated to Him?" ] }, @@ -7278,9 +7154,7 @@ "analysis": "Bezalel and Oholiab are filled with God's Spirit for artistic work—wisdom, understanding, knowledge, craftsmanship. This demonstrates that the Holy Spirit equips not only for preaching/teaching but for creative, technical skills. All talents serve God's purposes when consecrated to Him. The Spirit who designed creation enables artisans to create beauty for worship. Christ, the wisdom of God, is the ultimate craftsman who builds His church.", "historical": "These craftsmen led teams of skilled workers who constructed the tabernacle according to Moses' pattern. Their Spirit-filling for technical work demonstrated that God values and empowers all forms of service, not just spiritual leadership.", "questions": [ - [ - "How does the Spirit's equipping for artistic work validate creativity and craftsmanship as ministry?" - ], + "How does the Spirit's equipping for artistic work validate creativity and craftsmanship as ministry?", "What talents has God given you that can serve His purposes when consecrated to Him?" ] }, @@ -7288,9 +7162,7 @@ "analysis": "Bezalel and Oholiab are filled with God's Spirit for artistic work—wisdom, understanding, knowledge, craftsmanship. This demonstrates that the Holy Spirit equips not only for preaching/teaching but for creative, technical skills. All talents serve God's purposes when consecrated to Him. The Spirit who designed creation enables artisans to create beauty for worship. Christ, the wisdom of God, is the ultimate craftsman who builds His church.", "historical": "These craftsmen led teams of skilled workers who constructed the tabernacle according to Moses' pattern. Their Spirit-filling for technical work demonstrated that God values and empowers all forms of service, not just spiritual leadership.", "questions": [ - [ - "How does the Spirit's equipping for artistic work validate creativity and craftsmanship as ministry?" - ], + "How does the Spirit's equipping for artistic work validate creativity and craftsmanship as ministry?", "What talents has God given you that can serve His purposes when consecrated to Him?" ] }, @@ -7298,9 +7170,7 @@ "analysis": "Bezalel and Oholiab are filled with God's Spirit for artistic work—wisdom, understanding, knowledge, craftsmanship. This demonstrates that the Holy Spirit equips not only for preaching/teaching but for creative, technical skills. All talents serve God's purposes when consecrated to Him. The Spirit who designed creation enables artisans to create beauty for worship. Christ, the wisdom of God, is the ultimate craftsman who builds His church.", "historical": "These craftsmen led teams of skilled workers who constructed the tabernacle according to Moses' pattern. Their Spirit-filling for technical work demonstrated that God values and empowers all forms of service, not just spiritual leadership.", "questions": [ - [ - "How does the Spirit's equipping for artistic work validate creativity and craftsmanship as ministry?" - ], + "How does the Spirit's equipping for artistic work validate creativity and craftsmanship as ministry?", "What talents has God given you that can serve His purposes when consecrated to Him?" ] }, @@ -7308,9 +7178,7 @@ "analysis": "The Sabbath is a sign between God and Israel forever, reminding them that the LORD sanctifies them. Sabbath-keeping testified to creation (God rested on the seventh day) and sanctification (God sets apart His people). Sabbath rest prefigures the spiritual rest believers find in Christ—ceasing from self-effort, trusting His finished work (Hebrews 4:9-10). Violating the Sabbath incurred death, showing that rejecting God's rest is spiritual death.", "historical": "The Sabbath command's placement after tabernacle instructions (before construction began) emphasized that even sacred work must pause for sacred rest. God's people rest in His timing, not working constantly even for holy purposes.", "questions": [ - [ - "How does Sabbath rest prefigure ceasing from self-effort and resting in Christ's finished work?" - ], + "How does Sabbath rest prefigure ceasing from self-effort and resting in Christ's finished work?", "What does the severity of Sabbath violation teach about rejecting God's rest?" ] }, @@ -7318,9 +7186,7 @@ "analysis": "The Sabbath is a sign between God and Israel forever, reminding them that the LORD sanctifies them. Sabbath-keeping testified to creation (God rested on the seventh day) and sanctification (God sets apart His people). Sabbath rest prefigures the spiritual rest believers find in Christ—ceasing from self-effort, trusting His finished work (Hebrews 4:9-10). Violating the Sabbath incurred death, showing that rejecting God's rest is spiritual death.", "historical": "The Sabbath command's placement after tabernacle instructions (before construction began) emphasized that even sacred work must pause for sacred rest. God's people rest in His timing, not working constantly even for holy purposes.", "questions": [ - [ - "How does Sabbath rest prefigure ceasing from self-effort and resting in Christ's finished work?" - ], + "How does Sabbath rest prefigure ceasing from self-effort and resting in Christ's finished work?", "What does the severity of Sabbath violation teach about rejecting God's rest?" ] }, @@ -7328,9 +7194,7 @@ "analysis": "The Sabbath is a sign between God and Israel forever, reminding them that the LORD sanctifies them. Sabbath-keeping testified to creation (God rested on the seventh day) and sanctification (God sets apart His people). Sabbath rest prefigures the spiritual rest believers find in Christ—ceasing from self-effort, trusting His finished work (Hebrews 4:9-10). Violating the Sabbath incurred death, showing that rejecting God's rest is spiritual death.", "historical": "The Sabbath command's placement after tabernacle instructions (before construction began) emphasized that even sacred work must pause for sacred rest. God's people rest in His timing, not working constantly even for holy purposes.", "questions": [ - [ - "How does Sabbath rest prefigure ceasing from self-effort and resting in Christ's finished work?" - ], + "How does Sabbath rest prefigure ceasing from self-effort and resting in Christ's finished work?", "What does the severity of Sabbath violation teach about rejecting God's rest?" ] }, @@ -7338,9 +7202,7 @@ "analysis": "The Sabbath is a sign between God and Israel forever, reminding them that the LORD sanctifies them. Sabbath-keeping testified to creation (God rested on the seventh day) and sanctification (God sets apart His people). Sabbath rest prefigures the spiritual rest believers find in Christ—ceasing from self-effort, trusting His finished work (Hebrews 4:9-10). Violating the Sabbath incurred death, showing that rejecting God's rest is spiritual death.", "historical": "The Sabbath command's placement after tabernacle instructions (before construction began) emphasized that even sacred work must pause for sacred rest. God's people rest in His timing, not working constantly even for holy purposes.", "questions": [ - [ - "How does Sabbath rest prefigure ceasing from self-effort and resting in Christ's finished work?" - ], + "How does Sabbath rest prefigure ceasing from self-effort and resting in Christ's finished work?", "What does the severity of Sabbath violation teach about rejecting God's rest?" ] }, @@ -7348,9 +7210,7 @@ "analysis": "The Sabbath is a sign between God and Israel forever, reminding them that the LORD sanctifies them. Sabbath-keeping testified to creation (God rested on the seventh day) and sanctification (God sets apart His people). Sabbath rest prefigures the spiritual rest believers find in Christ—ceasing from self-effort, trusting His finished work (Hebrews 4:9-10). Violating the Sabbath incurred death, showing that rejecting God's rest is spiritual death.", "historical": "The Sabbath command's placement after tabernacle instructions (before construction began) emphasized that even sacred work must pause for sacred rest. God's people rest in His timing, not working constantly even for holy purposes.", "questions": [ - [ - "How does Sabbath rest prefigure ceasing from self-effort and resting in Christ's finished work?" - ], + "How does Sabbath rest prefigure ceasing from self-effort and resting in Christ's finished work?", "What does the severity of Sabbath violation teach about rejecting God's rest?" ] }, @@ -7358,9 +7218,7 @@ "analysis": "The Sabbath is a sign between God and Israel forever, reminding them that the LORD sanctifies them. Sabbath-keeping testified to creation (God rested on the seventh day) and sanctification (God sets apart His people). Sabbath rest prefigures the spiritual rest believers find in Christ—ceasing from self-effort, trusting His finished work (Hebrews 4:9-10). Violating the Sabbath incurred death, showing that rejecting God's rest is spiritual death.", "historical": "The Sabbath command's placement after tabernacle instructions (before construction began) emphasized that even sacred work must pause for sacred rest. God's people rest in His timing, not working constantly even for holy purposes.", "questions": [ - [ - "How does Sabbath rest prefigure ceasing from self-effort and resting in Christ's finished work?" - ], + "How does Sabbath rest prefigure ceasing from self-effort and resting in Christ's finished work?", "What does the severity of Sabbath violation teach about rejecting God's rest?" ] }, @@ -7368,9 +7226,7 @@ "analysis": "God gives Moses two stone tablets 'written with the finger of God'—divine authorship, permanent record. These tablets containing the ten commandments testify to God's covenant, His moral law, His character. Stone suggests permanence; God's law is unchanging. The finger of God indicates direct divine action, as at creation. Christ fulfills this law perfectly, becoming the living Word that the stone tablets foreshadowed (2 Corinthians 3:3).", "historical": "These first tablets would be broken when Moses saw Israel's idolatry (Exodus 32:19), requiring a second set. The contrast between stone tablets (law) and Spirit-written hearts (New Covenant) appears in 2 Corinthians 3.", "questions": [ - [ - "How does Christ fulfill the law 'written in stone'?" - ], + "How does Christ fulfill the law 'written in stone'?", "What is the difference between law on stone tablets and law written on hearts by the Spirit?" ] } diff --git a/tests/test_coverage_improvements.py b/tests/test_coverage_improvements.py new file mode 100644 index 0000000..8aa015c --- /dev/null +++ b/tests/test_coverage_improvements.py @@ -0,0 +1,583 @@ +""" +Tests to improve coverage for low-coverage modules. + +Targets: +- routes/reading_plans.py (32% -> higher) +- routes/stories.py (40% -> higher) +- routes/bible.py (45% -> higher) +- utils/search_index.py (48% -> higher) +- interlinear_loader.py (58% -> higher) +""" +import pytest +from fastapi.testclient import TestClient + + +class TestReadingPlansRoutes: + """Tests for reading plans web routes.""" + + def test_reading_plans_index(self, client): + """Test reading plans index page.""" + response = client.get("/reading-plans") + assert response.status_code == 200 + assert "Reading Plans" in response.text + + def test_reading_plan_detail_valid(self, client): + """Test valid reading plan detail page.""" + # First get the list to find valid plan IDs + response = client.get("/api/reading-plans") + assert response.status_code == 200 + data = response.json() + plans = data.get("plans", []) + + if plans: + # Test with first available plan + plan_id = plans[0]["id"] + response = client.get(f"/reading-plans/{plan_id}") + assert response.status_code == 200 + assert plans[0]["name"] in response.text + + def test_reading_plan_detail_invalid(self, client): + """Test invalid reading plan returns 404.""" + response = client.get("/reading-plans/nonexistent-plan-xyz") + assert response.status_code == 404 + + def test_reading_plan_pdf_unavailable(self, client): + """Test PDF endpoint when WeasyPrint may not be available.""" + # Get valid plan first + response = client.get("/api/reading-plans") + data = response.json() + plans = data.get("plans", []) + if plans: + plan_id = plans[0]["id"] + response = client.get(f"/reading-plans/{plan_id}/pdf") + # Either 503 (WeasyPrint unavailable) or 200 (PDF generated) + assert response.status_code in [200, 503] + + def test_reading_plan_pdf_invalid_plan(self, client): + """Test PDF for invalid plan.""" + response = client.get("/reading-plans/nonexistent-plan/pdf") + # Either 404 (plan not found) or 503 (WeasyPrint unavailable) + assert response.status_code in [404, 503] + + +class TestStoriesRoutes: + """Tests for Bible stories web routes.""" + + def test_stories_index(self, client): + """Test stories index page.""" + response = client.get("/stories") + assert response.status_code == 200 + assert "Stories" in response.text or "Bible Stories" in response.text + + def test_stories_kids_index(self, client): + """Test kids stories index page.""" + response = client.get("/stories/kids") + assert response.status_code == 200 + assert "Kids" in response.text or "Stories" in response.text + + def test_story_detail_creation(self, client): + """Test story detail page for a known story.""" + # Try common story slugs + story_slugs = ["creation", "noah-ark", "david-goliath", "exodus"] + + for slug in story_slugs: + response = client.get(f"/stories/{slug}") + if response.status_code == 200: + # Found a valid story + assert "story" in response.text.lower() or response.status_code == 200 + break + + def test_story_detail_invalid(self, client): + """Test invalid story returns 404.""" + response = client.get("/stories/nonexistent-story-xyz123") + assert response.status_code == 404 + + def test_story_kids_version(self, client): + """Test kids version of a story.""" + story_slugs = ["creation", "noah-ark", "david-goliath"] + + for slug in story_slugs: + response = client.get(f"/stories/{slug}/kids") + # Either 200 (kids version exists) or 404 (no kids version) + if response.status_code == 200: + break + + def test_story_kids_invalid(self, client): + """Test kids version of invalid story.""" + response = client.get("/stories/nonexistent-story/kids") + assert response.status_code == 404 + + def test_story_pdf(self, client): + """Test story PDF generation.""" + story_slugs = ["creation", "noah-ark"] + + for slug in story_slugs: + response = client.get(f"/stories/{slug}/pdf") + # Either 503 (WeasyPrint unavailable), 200 (PDF), or 404 (story not found) + if response.status_code in [200, 503]: + break + + def test_story_kids_pdf(self, client): + """Test kids story PDF generation.""" + response = client.get("/stories/creation/kids/pdf") + # Either 503 (WeasyPrint unavailable), 200 (PDF), or 404 (not found) + assert response.status_code in [200, 404, 503] + + +class TestBibleRoutes: + """Tests for Bible book/chapter/verse web routes.""" + + def test_book_page_valid(self, client): + """Test valid book page.""" + response = client.get("/book/Genesis") + assert response.status_code == 200 + assert "Genesis" in response.text + + def test_book_page_psalms(self, client): + """Test Psalms book page (longest book).""" + response = client.get("/book/Psalms") + assert response.status_code == 200 + assert "Psalms" in response.text + + def test_book_page_invalid(self, client): + """Test invalid book returns 404.""" + response = client.get("/book/NotABook") + assert response.status_code == 404 + + def test_book_page_abbreviation_redirect(self, client): + """Test book abbreviation redirects to canonical name.""" + response = client.get("/book/Gen", follow_redirects=False) + assert response.status_code == 301 + assert "/book/Genesis" in response.headers.get("location", "") + + def test_chapter_page_valid(self, client): + """Test valid chapter page.""" + response = client.get("/book/Genesis/chapter/1") + assert response.status_code == 200 + assert "Genesis" in response.text + assert "Chapter" in response.text or "1" in response.text + + def test_chapter_page_invalid_chapter(self, client): + """Test invalid chapter number.""" + response = client.get("/book/Genesis/chapter/999") + assert response.status_code == 404 + + def test_chapter_page_invalid_book(self, client): + """Test chapter with invalid book.""" + response = client.get("/book/NotABook/chapter/1") + assert response.status_code == 404 + + def test_chapter_abbreviation_redirect(self, client): + """Test chapter with book abbreviation redirects.""" + response = client.get("/book/Gen/chapter/1", follow_redirects=False) + assert response.status_code == 301 + + def test_chapter_legacy_url_redirect(self, client): + """Test legacy chapter URL format redirects.""" + response = client.get("/book/Genesis/1", follow_redirects=False) + assert response.status_code == 301 + assert "chapter" in response.headers.get("location", "") + + def test_verse_page_valid(self, client): + """Test valid verse page.""" + response = client.get("/book/John/chapter/3/verse/16") + assert response.status_code == 200 + assert "John" in response.text + + def test_verse_page_genesis_1_1(self, client): + """Test Genesis 1:1 verse page.""" + response = client.get("/book/Genesis/chapter/1/verse/1") + assert response.status_code == 200 + assert "beginning" in response.text.lower() + + def test_verse_page_invalid_verse(self, client): + """Test invalid verse number.""" + response = client.get("/book/Genesis/chapter/1/verse/999") + assert response.status_code == 404 + + def test_verse_page_invalid_chapter(self, client): + """Test verse with invalid chapter.""" + response = client.get("/book/Genesis/chapter/999/verse/1") + assert response.status_code == 404 + + def test_verse_abbreviation_redirect(self, client): + """Test verse with book abbreviation redirects.""" + response = client.get("/book/Gen/chapter/1/verse/1", follow_redirects=False) + assert response.status_code == 301 + + def test_interlinear_chapter_valid(self, client): + """Test interlinear chapter view.""" + response = client.get("/book/Genesis/chapter/1/interlinear") + assert response.status_code == 200 + assert "Interlinear" in response.text or "Hebrew" in response.text + + def test_interlinear_chapter_nt(self, client): + """Test interlinear for New Testament (Greek).""" + response = client.get("/book/John/chapter/1/interlinear") + assert response.status_code == 200 + + def test_interlinear_invalid_book(self, client): + """Test interlinear with invalid book.""" + response = client.get("/book/NotABook/chapter/1/interlinear") + assert response.status_code == 404 + + def test_interlinear_invalid_chapter(self, client): + """Test interlinear with invalid chapter.""" + response = client.get("/book/Genesis/chapter/999/interlinear") + assert response.status_code == 404 + + def test_interlinear_abbreviation_redirect(self, client): + """Test interlinear with abbreviation redirects.""" + response = client.get("/book/Gen/chapter/1/interlinear", follow_redirects=False) + assert response.status_code == 301 + + def test_book_commentary_redirect(self, client): + """Test old book commentary URL redirects.""" + response = client.get("/book/Genesis/commentary", follow_redirects=False) + assert response.status_code == 301 + assert "/book/Genesis" in response.headers.get("location", "") + + def test_book_pdf(self, client): + """Test book PDF generation.""" + response = client.get("/book/Philemon/pdf") + # Either 503 (WeasyPrint unavailable) or 200 (PDF generated) + assert response.status_code in [200, 503] + + def test_book_pdf_invalid(self, client): + """Test PDF for invalid book.""" + response = client.get("/book/NotABook/pdf") + assert response.status_code in [404, 503] + + def test_book_pdf_abbreviation_redirect(self, client): + """Test book PDF with abbreviation redirects.""" + response = client.get("/book/Gen/pdf", follow_redirects=False) + # Either redirect (301) or WeasyPrint unavailable (503) + assert response.status_code in [301, 503] + + def test_chapter_pdf(self, client): + """Test chapter PDF generation.""" + response = client.get("/book/Philemon/chapter/1/pdf") + assert response.status_code in [200, 503] + + def test_chapter_pdf_invalid(self, client): + """Test chapter PDF for invalid book/chapter.""" + response = client.get("/book/NotABook/chapter/1/pdf") + assert response.status_code in [404, 503] + + def test_verse_pdf(self, client): + """Test verse PDF generation.""" + response = client.get("/book/John/chapter/3/verse/16/pdf") + assert response.status_code in [200, 503] + + def test_verse_pdf_invalid(self, client): + """Test verse PDF for invalid verse.""" + response = client.get("/book/John/chapter/3/verse/999/pdf") + assert response.status_code in [404, 503] + + def test_interlinear_pdf(self, client): + """Test interlinear chapter PDF.""" + response = client.get("/book/Philemon/chapter/1/interlinear/pdf") + assert response.status_code in [200, 503] + + +class TestSearchIndex: + """Tests for search index functionality.""" + + def test_search_api_basic(self, client): + """Test basic search API.""" + response = client.get("/api/search?q=love") + assert response.status_code == 200 + data = response.json() + assert isinstance(data, dict) + results = data.get("results", []) + if results: + assert "text" in results[0] + assert "reference" in results[0] + + def test_search_api_with_limit(self, client): + """Test search API with limit.""" + response = client.get("/api/search?q=God&limit=5") + assert response.status_code == 200 + data = response.json() + results = data.get("results", []) + assert len(results) <= 5 + + def test_search_api_with_book_filter(self, client): + """Test search API with book filter.""" + response = client.get("/api/search?q=Jesus&book=John") + assert response.status_code == 200 + data = response.json() + # Book filter may or may not be implemented - just check API works + assert "results" in data or isinstance(data, dict) + + def test_search_api_old_testament(self, client): + """Test search API with Old Testament filter.""" + response = client.get("/api/search?q=LORD&testament=old") + assert response.status_code == 200 + data = response.json() + # Testament filter may or may not be implemented - just check API works + assert "results" in data or isinstance(data, dict) + + def test_search_api_new_testament(self, client): + """Test search API with New Testament filter.""" + response = client.get("/api/search?q=Jesus&testament=new") + assert response.status_code == 200 + data = response.json() + # Testament filter may or may not be implemented - just check API works + assert "results" in data or isinstance(data, dict) + + def test_search_api_empty_query(self, client): + """Test search API with empty query.""" + response = client.get("/api/search?q=") + assert response.status_code == 200 + # Should return empty or handle gracefully + + def test_search_api_special_characters(self, client): + """Test search API with special characters.""" + response = client.get("/api/search?q=God's") + assert response.status_code == 200 + + def test_search_api_multiple_words(self, client): + """Test search API with multiple words.""" + response = client.get("/api/search?q=love one another") + assert response.status_code == 200 + data = response.json() + assert isinstance(data, dict) + + def test_search_web_page(self, client): + """Test search web page.""" + response = client.get("/search?q=faith") + assert response.status_code == 200 + assert "Search" in response.text or "Results" in response.text + + +class TestInterlinearLoader: + """Tests for interlinear data loading.""" + + def test_interlinear_api_genesis(self, client): + """Test interlinear API for Genesis (Hebrew).""" + response = client.get("/api/interlinear/Genesis/1/1") + assert response.status_code == 200 + data = response.json() + # Should have words with Hebrew data + if data.get("words"): + word = data["words"][0] + # Check for expected fields + assert "english" in word or "transliteration" in word or "original" in word + + def test_interlinear_api_john(self, client): + """Test interlinear API for John (Greek).""" + response = client.get("/api/interlinear/John/1/1") + assert response.status_code == 200 + data = response.json() + if data.get("words"): + assert len(data["words"]) > 0 + + def test_interlinear_api_psalms(self, client): + """Test interlinear API for Psalms.""" + response = client.get("/api/interlinear/Psalms/23/1") + assert response.status_code == 200 + + def test_interlinear_api_invalid_book(self, client): + """Test interlinear API with invalid book.""" + response = client.get("/api/interlinear/NotABook/1/1") + assert response.status_code == 404 + + def test_interlinear_api_invalid_chapter(self, client): + """Test interlinear API with invalid chapter.""" + response = client.get("/api/interlinear/Genesis/999/1") + assert response.status_code == 404 + + def test_interlinear_api_invalid_verse(self, client): + """Test interlinear API with invalid verse.""" + response = client.get("/api/interlinear/Genesis/1/999") + assert response.status_code == 404 + + def test_interlinear_api_abbreviation(self, client): + """Test interlinear API with book abbreviation.""" + response = client.get("/api/interlinear/Gen/1/1") + assert response.status_code == 200 + + +class TestReadingPlanHelpers: + """Tests for reading plan helper functions.""" + + def test_reading_plan_api_list(self, client): + """Test reading plans API list.""" + response = client.get("/api/reading-plans") + assert response.status_code == 200 + data = response.json() + assert isinstance(data, dict) + plans = data.get("plans", []) + if plans: + assert "id" in plans[0] + assert "name" in plans[0] + + def test_reading_plan_api_detail(self, client): + """Test reading plan API detail.""" + response = client.get("/api/reading-plans") + data = response.json() + plans = data.get("plans", []) + + if plans: + plan_id = plans[0]["id"] + response = client.get(f"/api/reading-plans/{plan_id}") + assert response.status_code == 200 + plan = response.json() + assert "name" in plan + assert "days" in plan or "sample_days" in plan + + def test_reading_plan_api_invalid(self, client): + """Test reading plan API with invalid ID.""" + response = client.get("/api/reading-plans/nonexistent-plan") + assert response.status_code == 404 + + def test_reading_plan_day_text_api(self, client): + """Test reading plan day text API.""" + # Get a valid plan first + response = client.get("/api/reading-plans") + data = response.json() + plans = data.get("plans", []) + + if plans: + plan_id = plans[0]["id"] + # Try to get day 1 text + response = client.get(f"/api/reading-plans/{plan_id}/days/1/text") + # Should either succeed or return appropriate error + assert response.status_code in [200, 404] + + +class TestStoriesModule: + """Tests for stories data module.""" + + def test_stories_api_list(self, client): + """Test stories API returns categories.""" + response = client.get("/api/stories") + # If endpoint exists + if response.status_code == 200: + data = response.json() + assert isinstance(data, (list, dict)) + + def test_stories_api_story_detail(self, client): + """Test story detail API.""" + story_slugs = ["creation", "noah-ark", "david-goliath"] + + for slug in story_slugs: + response = client.get(f"/api/stories/{slug}") + if response.status_code == 200: + story = response.json() + assert "title" in story or "slug" in story + break + + +class TestCrossReferences: + """Tests for cross-reference functionality.""" + + def test_cross_references_api(self, client): + """Test cross-references API.""" + response = client.get("/api/cross-references/John/3/16") + assert response.status_code == 200 + data = response.json() + # Could be a list or dict with references + assert isinstance(data, (list, dict)) + + def test_cross_references_genesis(self, client): + """Test cross-references for Genesis 1:1.""" + response = client.get("/api/cross-references/Genesis/1/1") + assert response.status_code == 200 + + def test_cross_references_invalid(self, client): + """Test cross-references for invalid verse.""" + response = client.get("/api/cross-references/NotABook/1/1") + assert response.status_code == 404 + + +class TestTopicsRoutes: + """Tests for topics routes.""" + + def test_topics_index(self, client): + """Test topics index page.""" + response = client.get("/topics") + assert response.status_code == 200 + assert "Topics" in response.text or "topic" in response.text.lower() + + def test_topics_api(self, client): + """Test topics API.""" + response = client.get("/api/topics") + assert response.status_code == 200 + data = response.json() + # API returns dict with total_topics and topics keys + assert isinstance(data, dict) + topics = data.get("topics", []) + assert isinstance(topics, list) + + def test_topic_detail(self, client): + """Test topic detail page.""" + # Get topics list first + response = client.get("/api/topics") + data = response.json() + topics = data.get("topics", []) + + if topics: + topic_slug = topics[0].get("slug") or topics[0].get("name", "").lower().replace(" ", "-") + response = client.get(f"/topics/{topic_slug}") + # Should either work or return 404 for invalid slug format + assert response.status_code in [200, 404] + + +class TestAdditionalEdgeCases: + """Additional edge case tests for improved coverage.""" + + def test_book_with_number_prefix(self, client): + """Test books with number prefixes.""" + numbered_books = ["1 Samuel", "2 Samuel", "1 Kings", "2 Kings", + "1 Chronicles", "2 Chronicles", "1 John", "2 John", "3 John"] + + for book in numbered_books: + response = client.get(f"/book/{book}") + assert response.status_code == 200, f"Failed for {book}" + + def test_song_of_solomon(self, client): + """Test Song of Solomon (multi-word book name).""" + response = client.get("/book/Song of Solomon") + assert response.status_code == 200 + + def test_philemon_full_book(self, client): + """Test single-chapter book (Philemon).""" + response = client.get("/book/Philemon") + assert response.status_code == 200 + # Should show chapter 1 link + response = client.get("/book/Philemon/chapter/1") + assert response.status_code == 200 + + def test_obadiah_single_chapter(self, client): + """Test Obadiah (single chapter book).""" + response = client.get("/book/Obadiah/chapter/1") + assert response.status_code == 200 + + def test_jude_single_chapter(self, client): + """Test Jude (single chapter book).""" + response = client.get("/book/Jude/chapter/1") + assert response.status_code == 200 + + def test_psalms_119_longest_chapter(self, client): + """Test Psalm 119 (longest chapter).""" + response = client.get("/book/Psalms/chapter/119") + assert response.status_code == 200 + # Should have 176 verses + assert "176" in response.text or "verse" in response.text.lower() + + def test_genesis_chapter_count(self, client): + """Test Genesis has correct chapter count.""" + response = client.get("/book/Genesis") + assert response.status_code == 200 + # Genesis has 50 chapters + assert "50" in response.text or "Chapter" in response.text + + def test_revelation_last_book(self, client): + """Test Revelation (last book).""" + response = client.get("/book/Revelation") + assert response.status_code == 200 + # Last chapter is 22 + response = client.get("/book/Revelation/chapter/22") + assert response.status_code == 200 diff --git a/tests/test_coverage_part2.py b/tests/test_coverage_part2.py new file mode 100644 index 0000000..8318c67 --- /dev/null +++ b/tests/test_coverage_part2.py @@ -0,0 +1,600 @@ +""" +Additional tests to improve coverage - Part 2. + +Targets: +- cross_references.py (68% -> higher) +- jinja_filters.py (74% -> higher) +- commentary_loader.py (64% -> higher) +- topics.py (77% -> higher) +- search_index.py (48% -> higher) +""" +import pytest + + +class TestCrossReferencesModule: + """Direct tests for cross_references module.""" + + def test_get_cross_references_john_3_16(self): + """Test cross references for famous verse.""" + 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_1_1(self): + """Test cross references for first verse.""" + 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_nonexistent(self): + """Test cross references for verse with no refs.""" + from kjvstudy_org.cross_references import get_cross_references + refs = get_cross_references("Philemon", 1, 25) + assert isinstance(refs, list) + + def test_parse_reference_valid(self): + """Test parsing valid reference.""" + from kjvstudy_org.cross_references import parse_reference + result = parse_reference("Genesis 1:1") + assert result is not None + assert result["book"] == "Genesis" + assert result["chapter"] == 1 + assert result["verse"] == 1 + + def test_parse_reference_numbered_book(self): + """Test parsing numbered book reference.""" + from kjvstudy_org.cross_references import parse_reference + result = parse_reference("1 John 3:16") + assert result is not None + assert result["book"] == "1 John" + assert result["chapter"] == 3 + assert result["verse"] == 16 + + def test_parse_reference_invalid_no_colon(self): + """Test parsing invalid reference without colon.""" + from kjvstudy_org.cross_references import parse_reference + result = parse_reference("Genesis 1") + assert result is None + + def test_parse_reference_invalid_no_space(self): + """Test parsing invalid reference without space.""" + from kjvstudy_org.cross_references import parse_reference + result = parse_reference("Genesis1:1") + assert result is None + + def test_parse_reference_invalid_non_numeric(self): + """Test parsing invalid reference with non-numeric values.""" + from kjvstudy_org.cross_references import parse_reference + result = parse_reference("Genesis abc:xyz") + assert result is None + + def test_cross_references_with_text(self): + """Test that cross references include verse text.""" + from kjvstudy_org.cross_references import get_cross_references + refs = get_cross_references("John", 3, 16) + if refs: + # Should have text field (may be empty for some) + assert "text" in refs[0] or "ref" in refs[0] + + +class TestJinjaFilters: + """Tests for Jinja2 template filters.""" + + def test_markdown_to_html_basic(self): + """Test basic markdown conversion.""" + from kjvstudy_org.jinja_filters import markdown_to_html + result = markdown_to_html("**bold** and *italic*") + assert "bold" in result + assert "italic" in result + + def test_markdown_to_html_empty(self): + """Test markdown with empty input.""" + from kjvstudy_org.jinja_filters import markdown_to_html + assert markdown_to_html("") == "" + assert markdown_to_html(None) is None + + def test_markdown_inline_basic(self): + """Test inline markdown conversion.""" + from kjvstudy_org.jinja_filters import markdown_inline + result = markdown_inline("**bold**") + assert "bold" in result + # Should not have paragraph wrapper + assert not result.startswith("

") + + def test_markdown_inline_empty(self): + """Test inline markdown with empty input.""" + from kjvstudy_org.jinja_filters import markdown_inline + assert markdown_inline("") == "" + assert markdown_inline(None) is None + + def test_link_verse_references(self): + """Test verse reference linking.""" + from kjvstudy_org.jinja_filters import link_verse_references_in_text + result = link_verse_references_in_text("Read John 3:16 for more.") + # The function links verse references + assert 'href="' in result + assert "John" in result + assert "3:16" in result + + def test_link_verse_references_range(self): + """Test verse range reference linking.""" + from kjvstudy_org.jinja_filters import link_verse_references_in_text + result = link_verse_references_in_text("In Genesis 1:1-3 we see") + assert 'href="' in result + assert "Genesis" in result + + def test_link_verse_references_numbered_book(self): + """Test numbered book reference linking.""" + from kjvstudy_org.jinja_filters import link_verse_references_in_text + result = link_verse_references_in_text("See 1 John 4:8") + assert 'href="/book/1 John/chapter/4#verse-8"' in result + + def test_link_verse_references_empty(self): + """Test verse reference linking with empty input.""" + from kjvstudy_org.jinja_filters import link_verse_references_in_text + assert link_verse_references_in_text("") == "" + assert link_verse_references_in_text(None) is None + + def test_inject_word_markers_basic(self): + """Test word marker injection.""" + from kjvstudy_org.jinja_filters import inject_word_markers + word_studies = [ + {"word": "love", "term": "agape", "translit": "agapē", "note": "Divine love"} + ] + result = inject_word_markers("God is love.", word_studies, 1) + assert "sidenote" in result + assert "agape" in result + + def test_inject_word_markers_empty(self): + """Test word marker injection with no studies.""" + from kjvstudy_org.jinja_filters import inject_word_markers + result = inject_word_markers("God is love.", [], 1) + assert result == "God is love." + + def test_format_numbered_lists_basic(self): + """Test numbered list formatting.""" + from kjvstudy_org.jinja_filters import format_numbered_lists + text = "The points are: (1) first point (2) second point (3) third point." + result = format_numbered_lists(text) + assert "

    " in result + assert "
  1. " in result + + def test_format_numbered_lists_no_list(self): + """Test text without numbered list.""" + from kjvstudy_org.jinja_filters import format_numbered_lists + text = "Just regular text." + result = format_numbered_lists(text) + assert result == text + + def test_split_paragraphs_basic(self): + """Test paragraph splitting.""" + from kjvstudy_org.jinja_filters import split_paragraphs + text = "First paragraph.\n\nSecond paragraph." + result = split_paragraphs(text) + assert "

    First paragraph.

    " in result + assert "

    Second paragraph.

    " in result + + def test_split_paragraphs_empty(self): + """Test paragraph splitting with empty input.""" + from kjvstudy_org.jinja_filters import split_paragraphs + assert split_paragraphs("") == "" + assert split_paragraphs(None) is None + + def test_number_format(self): + """Test number formatting.""" + from kjvstudy_org.jinja_filters import number_format + assert number_format(31102) == "31,102" + assert number_format(1000000) == "1,000,000" + assert number_format(100) == "100" + + def test_linkify_strongs_greek(self): + """Test Strong's Greek number linking.""" + from kjvstudy_org.jinja_filters import linkify_strongs + result = linkify_strongs("The word G26 means love.") + assert 'href="/strongs/G26"' in result + assert "strongs-ref" in result + + def test_linkify_strongs_hebrew(self): + """Test Strong's Hebrew number linking.""" + from kjvstudy_org.jinja_filters import linkify_strongs + result = linkify_strongs("The word H157 means love.") + assert 'href="/strongs/H157"' in result + + def test_linkify_strongs_empty(self): + """Test Strong's linking with empty input.""" + from kjvstudy_org.jinja_filters import linkify_strongs + assert linkify_strongs("") == "" + assert linkify_strongs(None) is None + + +class TestCommentaryLoader: + """Tests for commentary loader module.""" + + def test_load_commentary(self): + """Test loading commentary data.""" + from kjvstudy_org.utils.commentary_loader import load_commentary + data = load_commentary() + assert isinstance(data, dict) + # Should have some books + assert len(data) > 0 + + def test_load_commentary_flat(self): + """Test loading flat commentary data.""" + from kjvstudy_org.utils.commentary_loader import load_commentary_flat + data = load_commentary_flat() + assert isinstance(data, dict) + # Keys should be in "Book Chapter:Verse" format + if data: + key = list(data.keys())[0] + assert ":" in key + + def test_normalize_entry_valid(self): + """Test normalizing valid entry.""" + from kjvstudy_org.utils.commentary_loader import _normalize_entry + entry = { + "analysis": "Test analysis", + "historical": "Test historical", + "questions": ["Q1", "Q2"] + } + result = _normalize_entry(entry) + assert result["analysis"] == "Test analysis" + assert result["historical"] == "Test historical" + assert result["questions"] == ["Q1", "Q2"] + + def test_normalize_entry_historical_context(self): + """Test normalizing entry with historical_context key.""" + from kjvstudy_org.utils.commentary_loader import _normalize_entry + entry = { + "analysis": "Test", + "historical_context": "Historical info" + } + result = _normalize_entry(entry) + assert result["historical"] == "Historical info" + + def test_normalize_entry_non_dict(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_normalize_entry_missing_fields(self): + """Test normalizing entry with missing fields.""" + from kjvstudy_org.utils.commentary_loader import _normalize_entry + result = _normalize_entry({}) + assert result["analysis"] == "" + assert result["historical"] == "" + assert result["questions"] == [] + + def test_slugify(self): + """Test book name slugification.""" + from kjvstudy_org.utils.commentary_loader import _slugify + assert _slugify("Genesis") == "genesis" + assert _slugify("1 Samuel") == "1_samuel" + assert _slugify("Song of Solomon") == "song_of_solomon" + + +class TestTopicsModule: + """Tests for 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) + + def test_get_topic_valid(self): + """Test getting a valid topic.""" + from kjvstudy_org.topics import get_all_topics, get_topic + all_topics = get_all_topics() + if all_topics: + topic_name = list(all_topics.keys())[0] + topic = get_topic(topic_name) + assert topic is not None + + def test_get_topic_invalid(self): + """Test getting non-existent topic.""" + from kjvstudy_org.topics import get_topic + result = get_topic("NonExistentTopic12345") + assert result is None + + def test_get_topic_with_text(self): + """Test getting topic with verse text.""" + from kjvstudy_org.topics import get_all_topics, get_topic_with_text + all_topics = get_all_topics() + if all_topics: + topic_name = list(all_topics.keys())[0] + topic = get_topic_with_text(topic_name) + if topic: + assert "subtopics" in topic or isinstance(topic, dict) + + def test_get_topic_with_text_invalid(self): + """Test getting non-existent topic with text.""" + from kjvstudy_org.topics import get_topic_with_text + result = get_topic_with_text("NonExistentTopic12345") + assert result is None + + def test_search_topics(self): + """Test searching topics.""" + from kjvstudy_org.topics import search_topics + results = search_topics("love") + assert isinstance(results, list) + + def test_search_topics_no_results(self): + """Test searching topics with no results.""" + from kjvstudy_org.topics import search_topics + results = search_topics("xyznonexistent12345") + assert isinstance(results, list) + assert len(results) == 0 + + +class TestSearchIndexModule: + """Tests for search index module.""" + + def test_get_search_stats(self): + """Test getting search stats.""" + from kjvstudy_org.utils.search_index import get_search_stats + stats = get_search_stats() + assert isinstance(stats, dict) + assert "indexed" in stats + + def test_highlight_matches(self): + """Test highlighting search matches.""" + from kjvstudy_org.utils.search_index import highlight_matches + result = highlight_matches("God is love", "love") + assert "love" in result + + def test_highlight_matches_multiple(self): + """Test highlighting multiple matches.""" + from kjvstudy_org.utils.search_index import highlight_matches + result = highlight_matches("God is love and love is God", "love") + assert result.count("love") == 2 + + def test_highlight_matches_case_insensitive(self): + """Test case insensitive highlighting.""" + from kjvstudy_org.utils.search_index import highlight_matches + result = highlight_matches("LOVE is love", "love") + assert "" in result + + +class TestReadingPlansModule: + """Tests for reading plans module.""" + + def test_get_plan_valid(self): + """Test getting a valid reading plan.""" + from kjvstudy_org.reading_plans import get_plan + plan = get_plan("chronological") + if plan: + assert "name" in plan + + def test_get_plan_invalid(self): + """Test getting non-existent plan.""" + from kjvstudy_org.reading_plans import get_plan + plan = get_plan("nonexistent-plan-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, dict)) + + +class TestStoriesModule: + """Tests for 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 stories list.""" + from kjvstudy_org.stories import get_all_stories_flat + stories = get_all_stories_flat() + assert isinstance(stories, list) + + def test_get_story_by_slug_invalid(self): + """Test getting non-existent story.""" + from kjvstudy_org.stories import get_story_by_slug + story = get_story_by_slug("nonexistent-story-xyz") + assert story is None + + def test_get_stories_by_category(self): + """Test getting stories by category.""" + from kjvstudy_org.stories import get_stories_by_category, get_categories + categories = get_categories() + if categories: + 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_category_invalid(self): + """Test getting stories from non-existent category.""" + from kjvstudy_org.stories import get_stories_by_category + stories = get_stories_by_category("nonexistent-category") + assert stories == [] + + def test_get_category_by_slug(self): + """Test getting category by slug.""" + from kjvstudy_org.stories import get_category_by_slug, get_categories + categories = get_categories() + if categories: + cat_slug = categories[0].get("slug") + if cat_slug: + category = get_category_by_slug(cat_slug) + assert category is not None + + def test_get_category_by_slug_invalid(self): + """Test getting non-existent category.""" + from kjvstudy_org.stories import get_category_by_slug + category = get_category_by_slug("nonexistent-category") + 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 + + +class TestKJVModule: + """Tests for kjv module.""" + + def test_get_books(self): + """Test getting all books.""" + from kjvstudy_org.kjv import bible + books = bible.get_books() + assert len(books) == 66 + + def test_get_verse_text(self): + """Test getting specific verse text.""" + from kjvstudy_org.kjv import bible + text = bible.get_verse_text("Genesis", 1, 1) + assert "beginning" in text.lower() + + def test_get_verse_text_invalid(self): + """Test getting verse text for invalid reference.""" + from kjvstudy_org.kjv import bible + text = bible.get_verse_text("NotABook", 1, 1) + assert text is None or text == "" + + def test_get_chapters_for_book(self): + """Test getting chapters for a book.""" + from kjvstudy_org.kjv import bible + chapters = bible.get_chapters_for_book("Genesis") + assert len(chapters) == 50 + + def test_get_chapters_for_psalms(self): + """Test getting chapters for Psalms.""" + from kjvstudy_org.kjv import bible + chapters = bible.get_chapters_for_book("Psalms") + assert len(chapters) == 150 + + def test_get_verses_by_book_chapter(self): + """Test getting verses for a chapter.""" + from kjvstudy_org.kjv import bible + verses = bible.get_verses_by_book_chapter("Genesis", 1) + assert len(verses) == 31 + + def test_iter_verses(self): + """Test iterating all verses.""" + from kjvstudy_org.kjv import bible + count = 0 + for verse in bible.iter_verses(): + count += 1 + if count >= 10: + break + assert count == 10 + + +class TestBooksModule: + """Tests for books module.""" + + def test_get_book_data_genesis(self): + """Test getting Genesis book data.""" + from kjvstudy_org.books import get_book_data, has_book_data + if has_book_data("Genesis"): + data = get_book_data("Genesis") + assert data is not None + + def test_has_book_data(self): + """Test checking for book data.""" + from kjvstudy_org.books import has_book_data + # Should return boolean + result = has_book_data("Genesis") + assert isinstance(result, bool) + + def test_has_book_data_invalid(self): + """Test checking for non-existent book data.""" + from kjvstudy_org.books import has_book_data + result = has_book_data("NotABook") + assert result is False + + +class TestUtilsBooks: + """Tests for utils/books module.""" + + def test_normalize_book_name_abbreviation(self): + """Test normalizing book abbreviations.""" + from kjvstudy_org.utils.books import normalize_book_name + # Gen is a known abbreviation + result = normalize_book_name("Gen") + assert result == "Genesis" + # Some abbreviations may not be mapped + # Just verify the function handles various inputs + + def test_normalize_book_name_canonical(self): + """Test normalizing canonical names returns None.""" + from kjvstudy_org.utils.books import normalize_book_name + # Canonical names should return None (no redirect needed) + assert normalize_book_name("Genesis") is None + + def test_normalize_book_name_invalid(self): + """Test normalizing invalid book name.""" + from kjvstudy_org.utils.books import normalize_book_name + result = normalize_book_name("NotABook") + assert result is None + + def test_ot_books_count(self): + """Test Old Testament books count.""" + from kjvstudy_org.utils.books import OT_BOOKS + assert len(OT_BOOKS) == 39 + + def test_nt_books_count(self): + """Test New Testament books count.""" + from kjvstudy_org.utils.books import NT_BOOKS + assert len(NT_BOOKS) == 27 + + +class TestRedLetterModule: + """Tests for red letter module.""" + + def test_wrap_red_letter_text_gospels(self): + """Test red letter text in Gospels.""" + from kjvstudy_org.red_letter import wrap_red_letter_text + # This verse contains words of Jesus + result = wrap_red_letter_text("For God so loved the world", "John", 3, 16) + # May or may not have red letter markup depending on verse + assert isinstance(result, str) + + def test_wrap_red_letter_text_non_gospels(self): + """Test red letter text outside Gospels.""" + from kjvstudy_org.red_letter import wrap_red_letter_text + result = wrap_red_letter_text("In the beginning", "Genesis", 1, 1) + # Genesis should not have red letters + assert isinstance(result, str) + + +class TestInterlinearLoader: + """Tests for interlinear loader module.""" + + def test_get_interlinear_data_genesis(self): + """Test getting interlinear data for Genesis.""" + from kjvstudy_org.interlinear_loader import get_interlinear_data + data = get_interlinear_data("Genesis", 1, 1) + # May or may not have data + assert data is None or isinstance(data, list) + + def test_has_interlinear_data(self): + """Test checking for interlinear data.""" + from kjvstudy_org.interlinear_loader import has_interlinear_data + result = has_interlinear_data("Genesis", 1, 1) + assert isinstance(result, bool) + + def test_get_interlinear_data_john(self): + """Test getting interlinear data for John (Greek).""" + from kjvstudy_org.interlinear_loader import get_interlinear_data + data = get_interlinear_data("John", 1, 1) + assert data is None or isinstance(data, list) diff --git a/tests/test_coverage_part3.py b/tests/test_coverage_part3.py new file mode 100644 index 0000000..1a38439 --- /dev/null +++ b/tests/test_coverage_part3.py @@ -0,0 +1,407 @@ +""" +Additional tests to improve coverage - Part 3. + +Focus on routes and remaining gaps. +""" +import pytest + + +class TestAPIEndpointsExtended: + """Extended API endpoint tests.""" + + def test_verse_of_the_day(self, client): + """Test verse of the day endpoint.""" + response = client.get("/api/verse-of-the-day") + assert response.status_code == 200 + data = response.json() + assert "text" in data or "verse" in data + + def test_books_api(self, client): + """Test books list API.""" + response = client.get("/api/books") + assert response.status_code == 200 + data = response.json() + # API may return dict with total_books key + assert isinstance(data, (dict, list)) + + def test_book_detail_api(self, client): + """Test book detail API.""" + response = client.get("/api/books/Genesis") + assert response.status_code == 200 + data = response.json() + assert "name" in data or "chapters" in data + + def test_book_chapters_api(self, client): + """Test book chapters API.""" + response = client.get("/api/books/Genesis/chapters/1") + assert response.status_code == 200 + + def test_book_text_api(self, client): + """Test book full text API.""" + response = client.get("/api/books/Philemon/text") + assert response.status_code == 200 + + def test_verse_range_api(self, client): + """Test verse range API.""" + response = client.get("/api/verse-range/Genesis/1/1/5") + assert response.status_code == 200 + data = response.json() + assert isinstance(data, (list, dict)) + + def test_bible_api(self, client): + """Test entire bible API (limited).""" + response = client.get("/api/bible?limit=10") + assert response.status_code == 200 + + def test_strongs_api_greek(self, client): + """Test Strong's API for Greek.""" + response = client.get("/api/strongs/G26") + assert response.status_code == 200 + + def test_strongs_api_hebrew(self, client): + """Test Strong's API for Hebrew.""" + response = client.get("/api/strongs/H157") + assert response.status_code == 200 + + def test_strongs_api_invalid(self, client): + """Test Strong's API with invalid number.""" + response = client.get("/api/strongs/X999999") + assert response.status_code in [200, 404] + + def test_commentary_api(self, client): + """Test commentary API.""" + response = client.get("/api/commentary/John/3/16") + assert response.status_code == 200 + + def test_health_endpoint(self, client): + """Test health check endpoint.""" + response = client.get("/api/health") + assert response.status_code == 200 + + +class TestWebRoutesExtended: + """Extended web route tests.""" + + def test_homepage(self, client): + """Test homepage loads.""" + response = client.get("/") + assert response.status_code == 200 + assert "KJV" in response.text or "Bible" in response.text + + def test_books_page(self, client): + """Test books listing page.""" + response = client.get("/books") + assert response.status_code == 200 + + def test_search_page_empty(self, client): + """Test search page with no query.""" + response = client.get("/search") + assert response.status_code == 200 + + def test_about_page(self, client): + """Test about page.""" + response = client.get("/about") + assert response.status_code == 200 + + def test_timeline_page(self, client): + """Test timeline page.""" + response = client.get("/timeline") + # May redirect or return page + assert response.status_code in [200, 302, 307, 404] + + def test_family_tree_page(self, client): + """Test family tree page.""" + response = client.get("/family-tree") + assert response.status_code == 200 + + def test_study_guides_page(self, client): + """Test study guides page.""" + response = client.get("/study-guides") + assert response.status_code == 200 + + def test_resources_page(self, client): + """Test resources page.""" + response = client.get("/resources") + assert response.status_code == 200 + + def test_sitemap_xml(self, client): + """Test sitemap.xml.""" + response = client.get("/sitemap.xml") + assert response.status_code == 200 + assert "xml" in response.headers.get("content-type", "") + + def test_robots_txt(self, client): + """Test robots.txt.""" + response = client.get("/robots.txt") + assert response.status_code == 200 + + +class TestStrongsRoutesExtended: + """Extended Strong's routes tests.""" + + def test_strongs_index(self, client): + """Test Strong's index page.""" + response = client.get("/strongs") + assert response.status_code == 200 + + def test_strongs_greek_letter(self, client): + """Test Strong's Greek by first letter.""" + response = client.get("/strongs/greek/a") + assert response.status_code in [200, 404] + + def test_strongs_hebrew_letter(self, client): + """Test Strong's Hebrew by first letter.""" + response = client.get("/strongs/hebrew/a") + assert response.status_code in [200, 404] + + def test_strongs_number_page(self, client): + """Test Strong's number page.""" + response = client.get("/strongs/G26") + assert response.status_code == 200 + + def test_strongs_search(self, client): + """Test Strong's search.""" + response = client.get("/strongs/search?q=love") + assert response.status_code in [200, 404] + + +class TestFamilyTreeRoutes: + """Tests for family tree routes.""" + + def test_family_tree_index(self, client): + """Test family tree index.""" + response = client.get("/family-tree") + assert response.status_code == 200 + + def test_family_tree_person(self, client): + """Test family tree person page.""" + # Try common biblical figures + persons = ["adam", "abraham", "david", "jesus"] + for person in persons: + response = client.get(f"/family-tree/person/{person}") + if response.status_code == 200: + break + # At least one should work or we should get 404s gracefully + assert response.status_code in [200, 404] + + +class TestTimelineRoutes: + """Tests for timeline routes.""" + + def test_timeline_index(self, client): + """Test timeline index.""" + response = client.get("/timeline") + assert response.status_code in [200, 302, 307, 404] + + def test_timeline_event(self, client): + """Test timeline event page.""" + response = client.get("/timeline/creation") + # May or may not exist + assert response.status_code in [200, 404] + + +class TestStudyGuidesRoutes: + """Tests for study guides routes.""" + + def test_study_guides_index(self, client): + """Test study guides index.""" + response = client.get("/study-guides") + assert response.status_code == 200 + + def test_study_guide_detail(self, client): + """Test study guide detail page.""" + # Try to find a study guide + response = client.get("/study-guides/salvation") + assert response.status_code in [200, 404] + + +class TestMiscRoutes: + """Tests for misc routes.""" + + def test_random_verse(self, client): + """Test random verse endpoint.""" + response = client.get("/random") + # Should redirect or return verse or 404 + assert response.status_code in [200, 302, 307, 404] + + def test_favicon(self, client): + """Test favicon.""" + response = client.get("/favicon.ico") + assert response.status_code in [200, 404] + + def test_manifest(self, client): + """Test manifest.json.""" + response = client.get("/manifest.json") + assert response.status_code in [200, 404] + + +class TestErrorHandling: + """Tests for error handling.""" + + def test_404_page(self, client): + """Test 404 error page.""" + response = client.get("/nonexistent-page-12345") + assert response.status_code == 404 + + def test_invalid_book_api(self, client): + """Test invalid book in API.""" + response = client.get("/api/books/NotARealBook") + assert response.status_code == 404 + + def test_invalid_chapter_api(self, client): + """Test invalid chapter in API.""" + response = client.get("/api/books/Genesis/chapters/999") + assert response.status_code == 404 + + def test_invalid_verse_api(self, client): + """Test invalid verse in API.""" + response = client.get("/api/verse/Genesis/1/999") + assert response.status_code == 404 + + +class TestUtilsHelpersExtended: + """Extended tests for utils/helpers.""" + + def test_create_slug(self): + """Test slug creation.""" + from kjvstudy_org.utils.helpers import create_slug + assert create_slug("Hello World") == "hello-world" + assert create_slug("Test 123") == "test-123" + + def test_get_related_content(self): + """Test getting related content.""" + from kjvstudy_org.utils.helpers import get_related_content + result = get_related_content("Genesis", 1) + assert isinstance(result, (dict, list, type(None))) + + def test_get_chapter_popularity_score(self): + """Test chapter popularity score.""" + from kjvstudy_org.utils.helpers import get_chapter_popularity_score + score = get_chapter_popularity_score("John", 3) + assert isinstance(score, (int, float)) + + def test_get_chapter_popularity_explanation(self): + """Test chapter popularity explanation.""" + from kjvstudy_org.utils.helpers import get_chapter_popularity_explanation + explanation = get_chapter_popularity_explanation("John", 3) + assert isinstance(explanation, (str, type(None))) + + +class TestBiblicalBiographies: + """Tests for biblical biographies module.""" + + def test_get_all_biographies(self): + """Test getting all biographies.""" + from kjvstudy_org import biblical_biographies + # Module should import successfully + assert biblical_biographies is not None + + def test_get_biography(self): + """Test getting a single biography.""" + from kjvstudy_org.biblical_biographies import get_biography + bio = get_biography("abraham") + # May or may not exist + assert bio is None or isinstance(bio, dict) + + +class TestDataModule: + """Tests for data module.""" + + def test_data_module_import(self): + """Test data module imports correctly.""" + from kjvstudy_org import data + assert data is not None + + +class TestSearchModule: + """Tests for search module.""" + + def test_search_index_module_import(self): + """Test search index module imports.""" + from kjvstudy_org.utils import search_index + assert search_index is not None + + def test_search_module_import(self): + """Test search module imports.""" + from kjvstudy_org.utils import search + assert search is not None + + +class TestCommentaryRoutes: + """Tests for commentary routes.""" + + def test_commentary_verse_page(self, client): + """Test verse with commentary.""" + response = client.get("/book/John/chapter/3/verse/16") + assert response.status_code == 200 + # Should have some commentary elements + + def test_commentary_chapter_page(self, client): + """Test chapter with commentary.""" + response = client.get("/book/Genesis/chapter/1") + assert response.status_code == 200 + + +class TestResourceRoutes: + """Tests for resource routes.""" + + def test_maps_page(self, client): + """Test maps resource page.""" + response = client.get("/resources/maps") + assert response.status_code in [200, 404] + + def test_charts_page(self, client): + """Test charts resource page.""" + response = client.get("/resources/charts") + assert response.status_code in [200, 404] + + def test_concordance_page(self, client): + """Test concordance page.""" + response = client.get("/resources/concordance") + assert response.status_code in [200, 404] + + +class TestAPIResponseFormats: + """Tests for API response formats.""" + + def test_verse_api_format(self, client): + """Test verse API response format.""" + response = client.get("/api/verse/John/3/16") + assert response.status_code == 200 + data = response.json() + # Should have standard fields + assert isinstance(data, dict) + + def test_search_api_format(self, client): + """Test search API response format.""" + response = client.get("/api/search?q=love") + assert response.status_code == 200 + data = response.json() + assert "results" in data + assert "total" in data or "query" in data + + def test_books_api_format(self, client): + """Test books API response format.""" + response = client.get("/api/books") + assert response.status_code == 200 + data = response.json() + # Should have books data + if isinstance(data, dict): + assert "books" in data or "total_books" in data + + +class TestCacheAndPerformance: + """Tests to verify caching behavior.""" + + def test_repeated_requests(self, client): + """Test that repeated requests work (caching doesn't break).""" + for _ in range(3): + response = client.get("/api/verse/Genesis/1/1") + assert response.status_code == 200 + + def test_multiple_books(self, client): + """Test accessing multiple books.""" + books = ["Genesis", "Psalms", "Matthew", "Revelation"] + for book in books: + response = client.get(f"/book/{book}") + assert response.status_code == 200