Something went wrong. Try again.
A fork of https://github.com/crosspoint-reader/crosspoint-reader
Something went wrong. Try again.
6.1 kB · 142 lines
C++
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143#include <gtest/gtest.h>
#include <memory>#include <string>#include <utility>#include <vector>
#include "ChapterXPathResolver.h"
namespace {std::shared_ptr<Epub> epubWith(std::string xhtml) { std::vector<std::string> spine; spine.push_back(std::move(xhtml)); return std::make_shared<Epub>(std::move(spine));}
constexpr char kNestedFixture[] = R"(<?xml version="1.0" encoding="UTF-8"?><html xmlns="http://www.w3.org/1999/xhtml"><body><div><section><p>Alpha bravo</p><p>Second <em>nested</em> tail</p></section></div></body></html>)";
constexpr char kNonVisibleInlineFixture[] = R"(<html><body><p><RP><span>hidden</span></RP>Visible text</p></body></html>)";
constexpr char kCommentBoundaryFixture[] = R"(<html><body><p>before<!--comment-->after</p></body></html>)";constexpr char kProcessingInstructionBoundaryFixture[] = R"(<html><body><p>before<?marker?>after</p></body></html>)";constexpr char kCdataBoundaryFixture[] = R"(<html><body><p>before<![CDATA[middle]]>after</p></body></html>)";constexpr char kHiddenCdataFixture[] = R"(<html><body><p>before<rp><![CDATA[hidden]]></rp>after</p></body></html>)";} // namespace
TEST(KOReaderXPathResolver, ResolvesExactOffsetWithFullAncestry) { const auto epub = epubWith(kNestedFixture);
EXPECT_EQ(ChapterXPathResolver::findXPathForVisibleTextOffset(epub, 0, 6), "/body/DocFragment[1]/body/div[1]/section[1]/p[1]/text()[1].6");}
TEST(KOReaderXPathResolver, PreservesNestedInlineTextNode) { const auto epub = epubWith(kNestedFixture);
EXPECT_EQ(ChapterXPathResolver::findXPathForVisibleTextOffset(epub, 0, 26), "/body/DocFragment[1]/body/div[1]/section[1]/p[2]/text()[2].2");}
TEST(KOReaderXPathResolver, EmitsDetailedAnchorForOffsetZero) { const auto epub = epubWith(kNestedFixture);
EXPECT_EQ(ChapterXPathResolver::findXPathForVisibleTextOffset(epub, 0, 0), "/body/DocFragment[1]/body/div[1]/section[1]/p[1]/text()[1].0");}
TEST(KOReaderXPathResolver, IgnoresNestedNonVisibleInlineText) { const auto epub = epubWith(kNonVisibleInlineFixture);
EXPECT_EQ(ChapterXPathResolver::findXPathForVisibleTextOffset(epub, 0, 0), "/body/DocFragment[1]/body/p[1]/text()[1].0");}
TEST(KOReaderXPathResolver, ResolvesProgressAfterNestedNonVisibleInlineText) { const auto epub = epubWith(kNonVisibleInlineFixture);
EXPECT_EQ(ChapterXPathResolver::findXPathForProgress(epub, 0, 1.0f), "/body/DocFragment[1]/body/p[1]/text()[1].12");}
TEST(KOReaderXPathResolver, CountsUtf8CodepointsInsteadOfBytes) { const auto epub = epubWith( "<?xml version=\"1.0\" encoding=\"UTF-8\"?><html><body><p>A\xC3\xA9\xE4\xB8\xAD" "B</p></body></html>");
EXPECT_EQ(ChapterXPathResolver::findXPathForVisibleTextOffset(epub, 0, 3), "/body/DocFragment[1]/body/p[1]/text()[1].3");}
TEST(KOReaderXPathResolver, SplitsTextNodesAroundComments) { const auto epub = epubWith(kCommentBoundaryFixture);
EXPECT_EQ(ChapterXPathResolver::findXPathForVisibleTextOffset(epub, 0, 6), "/body/DocFragment[1]/body/p[1]/text()[2].0"); EXPECT_TRUE(ChapterXPathResolver::findXPathForVisibleTextOffset(epub, 0, 11).empty()); EXPECT_EQ(ChapterXPathResolver::findXPathForVisibleTextOffset(epub, 0, 7), "/body/DocFragment[1]/body/p[1]/text()[2].1");}
TEST(KOReaderXPathResolver, SplitsTextNodesAroundProcessingInstructions) { const auto epub = epubWith(kProcessingInstructionBoundaryFixture);
EXPECT_EQ(ChapterXPathResolver::findXPathForVisibleTextOffset(epub, 0, 7), "/body/DocFragment[1]/body/p[1]/text()[2].1");}
TEST(KOReaderXPathResolver, SplitsTextNodesAroundCdata) { const auto epub = epubWith(kCdataBoundaryFixture);
EXPECT_EQ(ChapterXPathResolver::findXPathForVisibleTextOffset(epub, 0, 7), "/body/DocFragment[1]/body/p[1]/text()[2].1"); EXPECT_EQ(ChapterXPathResolver::findXPathForVisibleTextOffset(epub, 0, 13), "/body/DocFragment[1]/body/p[1]/text()[3].1");}
TEST(KOReaderXPathResolver, DoesNotCreateNodesBeforeFirstComment) { const auto epub = epubWith(R"(<html><body><p><!--comment-->text</p></body></html>)");
EXPECT_EQ(ChapterXPathResolver::findXPathForVisibleTextOffset(epub, 0, 0), "/body/DocFragment[1]/body/p[1]/text()[1].0");}
TEST(KOReaderXPathResolver, DoesNotCreateNodesBeforeFirstProcessingInstruction) { const auto epub = epubWith(R"(<html><body><p><?marker?>text</p></body></html>)");
EXPECT_EQ(ChapterXPathResolver::findXPathForVisibleTextOffset(epub, 0, 0), "/body/DocFragment[1]/body/p[1]/text()[1].0");}
TEST(KOReaderXPathResolver, DoesNotCreateNodesBeforeFirstCdata) { const auto epub = epubWith(R"(<html><body><p><![CDATA[text]]></p></body></html>)");
EXPECT_EQ(ChapterXPathResolver::findXPathForVisibleTextOffset(epub, 0, 0), "/body/DocFragment[1]/body/p[1]/text()[1].0");}
TEST(KOReaderXPathResolver, CountsVisibleCdataAndIgnoresHiddenCdata) { const auto visible = epubWith(kCdataBoundaryFixture); const auto hidden = epubWith(kHiddenCdataFixture);
EXPECT_EQ(ChapterXPathResolver::findXPathForVisibleTextOffset(visible, 0, 7), "/body/DocFragment[1]/body/p[1]/text()[2].1"); EXPECT_EQ(ChapterXPathResolver::findXPathForVisibleTextOffset(hidden, 0, 7), "/body/DocFragment[1]/body/p[1]/text()[2].1");}
TEST(KOReaderXPathResolver, ReturnsEmptyForUnusableContent) { EXPECT_TRUE(ChapterXPathResolver::findXPathForVisibleTextOffset(epubWith(""), 0, 0).empty()); EXPECT_TRUE(ChapterXPathResolver::findXPathForVisibleTextOffset(epubWith("<html><body><p>broken"), 0, 100).empty()); EXPECT_TRUE(ChapterXPathResolver::findXPathForVisibleTextOffset( epubWith("<html><body><div>not a paragraph or list item</div></body></html>"), 0, 0) .empty());}
TEST(KOReaderXPathResolver, KeepsParagraphOnlyResolutionUnchanged) { const auto epub = epubWith(kNestedFixture);
EXPECT_EQ(ChapterXPathResolver::findXPathForParagraph(epub, 0, 2), "/body/DocFragment[1]/body/div[1]/section[1]/p[2]");}