From 562e32c373d72421b5f12a639f392e5813b1df8d Mon Sep 17 00:00:00 2001 From: Peter Chapman Date: Tue, 3 Feb 2026 11:16:51 +1300 Subject: [PATCH] SF-3680 Ensure that a verse that is not in a para has a blank segment --- .../Services/DeltaUsxMapper.cs | 1 + .../Services/DeltaUsxMapperTests.cs | 75 +++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/src/SIL.XForge.Scripture/Services/DeltaUsxMapper.cs b/src/SIL.XForge.Scripture/Services/DeltaUsxMapper.cs index 70b1a27fa58..1227688753d 100644 --- a/src/SIL.XForge.Scripture/Services/DeltaUsxMapper.cs +++ b/src/SIL.XForge.Scripture/Services/DeltaUsxMapper.cs @@ -235,6 +235,7 @@ public IEnumerable ToChapterDeltas(XDocument usxDoc) case "para": if (state.ImpliedParagraph) { + SegmentEnded(chapterDelta, state.CurRef); chapterDelta.Insert('\n'); state.ImpliedParagraph = false; } diff --git a/test/SIL.XForge.Scripture.Tests/Services/DeltaUsxMapperTests.cs b/test/SIL.XForge.Scripture.Tests/Services/DeltaUsxMapperTests.cs index c6bf0d1053f..48680698421 100644 --- a/test/SIL.XForge.Scripture.Tests/Services/DeltaUsxMapperTests.cs +++ b/test/SIL.XForge.Scripture.Tests/Services/DeltaUsxMapperTests.cs @@ -1152,6 +1152,57 @@ public void ToUsx_ImpliedParagraphTwice() Assert.IsTrue(XNode.DeepEquals(newUsxDoc, expected)); } + [Test] + public void ToUsx_ImpliedParagraphForVerseWithEmptyParagraphAfter() + { + var chapterDelta = new ChapterDelta( + 1, + 1, + true, + Delta + .New() + .InsertBook("PHM") + .InsertChapter("1") + .InsertVerse("1") + .InsertBlank("verse_1_1") + .Insert("\n") + .InsertBlank("verse_1_1/p_1") + .InsertPara("p") + ); + + var mapper = new DeltaUsxMapper(_mapperGuidService, _logger, _exceptionHandler); + XDocument newUsxDoc = mapper.ToUsx(Usx("PHM"), [chapterDelta]); + + XDocument expected = Usx("PHM", Chapter("1"), Verse("1"), Para("p")); + Assert.IsTrue(XNode.DeepEquals(newUsxDoc, expected)); + } + + [Test] + public void ToUsx_ImpliedParagraphMissingForVerseWithEmptyParagraphAfter() + { + // This is the same test as ToUsx_ImpliedParagraphForVerseWithEmptyParagraphAfter + // but with deltas created before SF-3680 + var chapterDelta = new ChapterDelta( + 1, + 1, + true, + Delta + .New() + .InsertBook("PHM") + .InsertChapter("1") + .InsertVerse("1") + .Insert("\n") + .InsertBlank("verse_1_1/p_1") + .InsertPara("p") + ); + + var mapper = new DeltaUsxMapper(_mapperGuidService, _logger, _exceptionHandler); + XDocument newUsxDoc = mapper.ToUsx(Usx("PHM"), [chapterDelta]); + + XDocument expected = Usx("PHM", Chapter("1"), Verse("1"), Para("p")); + Assert.IsTrue(XNode.DeepEquals(newUsxDoc, expected)); + } + [Test] public void ToUsx_ImpliedParagraphInVerse() { @@ -3271,6 +3322,30 @@ public void ToDelta_ImpliedParagraph() Assert.IsTrue(chapterDeltas[0].Delta.DeepEquals(expected)); } + [Test] + public void ToDelta_ImpliedParagraphForVerseWithEmptyParagraphAfter() + { + XDocument usxDoc = Usx("PHM", Chapter("1"), Verse("1"), Para("p")); + + var mapper = new DeltaUsxMapper(_mapperGuidService, _logger, _exceptionHandler); + List chapterDeltas = [.. mapper.ToChapterDeltas(usxDoc)]; + + var expected = Delta + .New() + .InsertBook("PHM") + .InsertChapter("1") + .InsertVerse("1") + .InsertBlank("verse_1_1") + .Insert("\n") + .InsertBlank("verse_1_1/p_1") + .InsertPara("p"); + + Assert.That(chapterDeltas[0].Number, Is.EqualTo(1)); + Assert.That(chapterDeltas[0].LastVerse, Is.EqualTo(1)); + Assert.That(chapterDeltas[0].IsValid, Is.True); + Assert.IsTrue(chapterDeltas[0].Delta.DeepEquals(expected)); + } + [Test] public void ToDelta_ImpliedParagraphInVerse() {