diff --git a/src/server/internalServer.cpp b/src/server/internalServer.cpp index 1e0fe8a26..eb43286bd 100644 --- a/src/server/internalServer.cpp +++ b/src/server/internalServer.cpp @@ -517,6 +517,7 @@ std::unique_ptr InternalServer::handle_search(const RequestContext& re || (patternString.empty() && ! has_geo_query) ) { auto data = get_default_data(); data.set("pattern", encodeDiples(patternString)); + data.set("root", m_root); auto response = ContentResponse::build(*this, RESOURCE::templates::no_search_result_html, data, "text/html; charset=utf-8"); response->set_taskbar(bookName, archive ? getArchiveTitle(*archive) : ""); response->set_code(MHD_HTTP_NOT_FOUND); diff --git a/static/resources_list.txt b/static/resources_list.txt index b0b7a336a..5587111c0 100644 --- a/static/resources_list.txt +++ b/static/resources_list.txt @@ -32,6 +32,7 @@ skin/index.css skin/fonts/Poppins.ttf skin/fonts/Roboto.ttf skin/block_external.js +skin/search_results.css templates/search_result.html templates/no_search_result.html templates/404.html diff --git a/static/skin/search_results.css b/static/skin/search_results.css new file mode 100644 index 000000000..8fb0a84b1 --- /dev/null +++ b/static/skin/search_results.css @@ -0,0 +1,87 @@ +body{ +background-color: white; +color: #000000; +font: small/normal Arial,Helvetica,Sans-Serif; +margin-top: 0.5em; +font-size: 90%; +} + +a{ +color: #04c; +} + +a:visited { +color: #639 +} + +a:hover { +text-decoration: underline +} + +.header { +font-size: 120%; +} + +ul { +margin:0; +padding:0 +} + +.results { +font-size: 110%; +} + +.results li { +list-style-type:none; +margin-top: 0.5em; +} + +.results a { +font-size: 110%; +text-decoration: underline +} + +cite { +font-style:normal; +word-wrap:break-word; +display: block; +font-size: 100%; +} + +.informations { +color: #388222; +font-size: 100%; +} + +.footer { +padding: 0; +margin-top: 1em; +width: 100%; +float: left +} + +.footer a, .footer span { +display: block; +padding: .3em .7em; +margin: 0 .38em 0 0; +text-align:center; +text-decoration: none; +} + +.footer a:hover { +background: #ededed; +} + +.footer ul, .footer li { +list-style:none; +margin: 0; +padding: 0; +} + +.footer li { +float: left; +} + +.selected { +background: #ededed; +} diff --git a/static/templates/404.html b/static/templates/404.html index 55645dbd7..2f6cf2acf 100644 --- a/static/templates/404.html +++ b/static/templates/404.html @@ -1,5 +1,5 @@ - + Content not found diff --git a/static/templates/no_search_result.html b/static/templates/no_search_result.html index 104708850..baa7aa2c7 100644 --- a/static/templates/no_search_result.html +++ b/static/templates/no_search_result.html @@ -1,99 +1,11 @@ - - + Fulltext search unavailable + - +
Not found

There is no article with the title "{{pattern}}" diff --git a/test/server.cpp b/test/server.cpp index bff14f654..4eb22e063 100644 --- a/test/server.cpp +++ b/test/server.cpp @@ -303,6 +303,7 @@ const char* urls404[] = { "/ROOT/random", "/ROOT/random?content=non-existent-book", "/ROOT/search", + "/ROOT/search?content=non-existing-book&pattern=asdfqwerty", "/ROOT/suggest", "/ROOT/suggest?content=non-existent-book&term=abcd", "/ROOT/catch/external", @@ -327,11 +328,17 @@ namespace TestingOfHtmlResponses struct ExpectedResponseData { - const std::string bookName, bookTitle, expectedBody; + const std::string expectedPageTitle; + const std::string expectedCssUrl; + const std::string bookName; + const std::string bookTitle; + const std::string expectedBody; }; enum ExpectedResponseDataType { + expected_page_title, + expected_css_url, book_name, book_title, expected_body @@ -344,9 +351,11 @@ ExpectedResponseData operator==(ExpectedResponseDataType t, std::string s) { switch (t) { - case book_name: return ExpectedResponseData{s, "", ""}; - case book_title: return ExpectedResponseData{"", s, ""}; - case expected_body: return ExpectedResponseData{"", "", s}; + case expected_page_title: return ExpectedResponseData{s, "", "", "", ""}; + case expected_css_url: return ExpectedResponseData{"", s, "", "", ""}; + case book_name: return ExpectedResponseData{"", "", s, "", ""}; + case book_title: return ExpectedResponseData{"", "", "", s, ""}; + case expected_body: return ExpectedResponseData{"", "", "", "", s}; default: assert(false); return ExpectedResponseData{}; } } @@ -363,6 +372,8 @@ ExpectedResponseData operator&&(const ExpectedResponseData& a, const ExpectedResponseData& b) { return ExpectedResponseData{ + selectNonEmpty(a.expectedPageTitle, b.expectedPageTitle), + selectNonEmpty(a.expectedCssUrl, b.expectedCssUrl), selectNonEmpty(a.bookName, b.bookName), selectNonEmpty(a.bookTitle, b.bookTitle), selectNonEmpty(a.expectedBody, b.expectedBody) @@ -383,6 +394,8 @@ public: std::string expectedResponse() const; private: + std::string pageTitle() const; + std::string pageCssLink() const; std::string hiddenBookNameInput() const; std::string searchPatternInput() const; std::string taskbarLinks() const; @@ -392,11 +405,15 @@ std::string TestContentIn404HtmlResponse::expectedResponse() const { const std::string frag[] = { R"FRAG( - + - Content not found - + )FRAG", + + R"FRAG( +)FRAG", + + R"FRAG( @@ -435,14 +452,36 @@ std::string TestContentIn404HtmlResponse::expectedResponse() const }; return frag[0] - + hiddenBookNameInput() + + pageTitle() + frag[1] - + searchPatternInput() + + pageCssLink() + frag[2] - + taskbarLinks() + + hiddenBookNameInput() + frag[3] + + searchPatternInput() + + frag[4] + + taskbarLinks() + + frag[5] + removeEOLWhitespaceMarkers(expectedBody) - + frag[4]; + + frag[6]; +} + +std::string TestContentIn404HtmlResponse::pageTitle() const +{ + return expectedPageTitle.empty() + ? "Content not found" + : expectedPageTitle; +} + +std::string TestContentIn404HtmlResponse::pageCssLink() const +{ + if ( expectedCssUrl.empty() ) + return ""; + + return R"( +)"; } std::string TestContentIn404HtmlResponse::hiddenBookNameInput() const @@ -623,6 +662,30 @@ TEST_F(ServerTest, 404WithBodyTesting) Cannot find content entry invalid-article

)" }, + + { /* url */ "/ROOT/search?content=zimfile", + expected_page_title=="Fulltext search unavailable" && + expected_css_url=="/ROOT/skin/search_results.css" && + book_name=="zimfile" && + book_title=="Ray Charles" && + expected_body==R"( +
Not found
+

+ There is no article with the title "" + and the fulltext search engine is not available for this content. +

+)" }, + + { /* url */ "/ROOT/search?content=non-existent-book&pattern=asdfqwerty", + expected_page_title=="Fulltext search unavailable" && + expected_css_url=="/ROOT/skin/search_results.css" && + expected_body==R"( +
Not found
+

+ There is no article with the title "asdfqwerty" + and the fulltext search engine is not available for this content. +

+)" }, }; for ( const auto& t : testData ) {