From cf53a7c678ceb04a70855de45f1cbf9eb524d096 Mon Sep 17 00:00:00 2001 From: James Addison Date: Fri, 15 Mar 2024 18:26:56 +0000 Subject: [PATCH 01/17] [tests] JavaScript: extract searchindex.js-format test fixtures --- karma.conf.js | 3 ++- tests/js/fixtures/index.cpp.js | 15 +++++++++++ tests/js/fixtures/index.multiterm.js | 22 ++++++++++++++++ tests/js/searchtools.js | 39 ++++++++++++---------------- 4 files changed, 55 insertions(+), 24 deletions(-) create mode 100644 tests/js/fixtures/index.cpp.js create mode 100644 tests/js/fixtures/index.multiterm.js diff --git a/karma.conf.js b/karma.conf.js index 8a18e80ba7a..5f20030596a 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -19,7 +19,8 @@ module.exports = function(config) { 'sphinx/themes/basic/static/doctools.js', 'sphinx/themes/basic/static/searchtools.js', 'sphinx/themes/basic/static/sphinx_highlight.js', - 'tests/js/*.js' + 'tests/js/*.js', + { pattern: 'tests/js/fixtures/*.js', included: false, served: true } ], diff --git a/tests/js/fixtures/index.cpp.js b/tests/js/fixtures/index.cpp.js new file mode 100644 index 00000000000..8e8cb65e91e --- /dev/null +++ b/tests/js/fixtures/index.cpp.js @@ -0,0 +1,15 @@ +Search.setIndex({ + docnames: [ + "index" + ], + filenames: [ + "index.rst" + ], + terms: { + "c++" : 0 + }, + titles: [ + "<no title>" + ], + titleterms: {} +}); diff --git a/tests/js/fixtures/index.multiterm.js b/tests/js/fixtures/index.multiterm.js new file mode 100644 index 00000000000..d1290e71827 --- /dev/null +++ b/tests/js/fixtures/index.multiterm.js @@ -0,0 +1,22 @@ +Search.setIndex({ + alltitles: { + "Main Page": [[0, "main-page"]] + }, + docnames: [ + "index" + ], + filenames: [ + "index.rst" + ], + terms: { + main: 0, + page: 0 + }, + titles: [ + "Main Page" + ], + titleterms : { + main: 0, + page: 0 + } +}); diff --git a/tests/js/searchtools.js b/tests/js/searchtools.js index 91c35a6ba14..47d5e6efb43 100644 --- a/tests/js/searchtools.js +++ b/tests/js/searchtools.js @@ -1,20 +1,22 @@ describe('Basic html theme search', function() { + function loadFixture(name) { + req = new XMLHttpRequest(); + req.open("GET", `base/tests/js/fixtures/${name}`, false); + req.send(null); + return req.responseText; + } + describe('terms search', function() { it('should find "C++" when in index', function() { - index = { - docnames:["index"], - filenames:["index.rst"], - terms:{'c++':0}, - titles:["<no title>"], - titleterms:{} - } - Search.setIndex(index); + searchindex = loadFixture("index.cpp.js"); + eval(searchindex); + searchterms = ['c++']; excluded = []; - terms = index.terms; - titleterms = index.titleterms; + terms = Search._index.terms; + titleterms = Search._index.titleterms; hits = [[ "index", @@ -28,22 +30,13 @@ describe('Basic html theme search', function() { }); it('should be able to search for multiple terms', function() { - index = { - alltitles: { - 'Main Page': [[0, 'main-page']], - }, - docnames:["index"], - filenames:["index.rst"], - terms:{main:0, page:0}, - titles:["Main Page"], - titleterms:{ main:0, page:0 } - } - Search.setIndex(index); + searchindex = loadFixture("index.multiterm.js"); + eval(searchindex); searchterms = ['main', 'page']; excluded = []; - terms = index.terms; - titleterms = index.titleterms; + terms = Search._index.terms; + titleterms = Search._index.titleterms; hits = [[ 'index', 'Main Page', From 311c4f05f8f9a8de1c5d1b0beae829bb91cbd8a5 Mon Sep 17 00:00:00 2001 From: James Addison Date: Fri, 15 Mar 2024 22:23:25 +0000 Subject: [PATCH 02/17] [tests] JavaScript: write Sphinx sources that produce acceptable searchindex.js test fixtures --- .gitignore | 1 + tests/js/fixtures/index.cpp.js | 16 +--------------- tests/js/fixtures/index.multiterm.js | 23 +---------------------- tests/js/roots/cpp/conf.py | 14 ++++++++++++++ tests/js/roots/cpp/index.rst | 5 +++++ tests/js/roots/multiterm/conf.py | 0 tests/js/roots/multiterm/index.rst | 4 ++++ 7 files changed, 26 insertions(+), 37 deletions(-) create mode 100644 tests/js/roots/cpp/conf.py create mode 100644 tests/js/roots/cpp/index.rst create mode 100644 tests/js/roots/multiterm/conf.py create mode 100644 tests/js/roots/multiterm/index.rst diff --git a/.gitignore b/.gitignore index a2f7d63b3ad..3c87572d26f 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,7 @@ doc/_build/ doc/locale/ tests/.coverage tests/build/ +tests/js/roots/*/build tests/test-server.lock utils/regression_test.js diff --git a/tests/js/fixtures/index.cpp.js b/tests/js/fixtures/index.cpp.js index 8e8cb65e91e..8be181211a9 100644 --- a/tests/js/fixtures/index.cpp.js +++ b/tests/js/fixtures/index.cpp.js @@ -1,15 +1 @@ -Search.setIndex({ - docnames: [ - "index" - ], - filenames: [ - "index.rst" - ], - terms: { - "c++" : 0 - }, - titles: [ - "<no title>" - ], - titleterms: {} -}); +Search.setIndex({"alltitles": {}, "docnames": ["index"], "envversion": {"sphinx": 61, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2}, "filenames": ["index.rst"], "indexentries": {"sphinx (c++ class)": [[0, "_CPPv46Sphinx"]]}, "objects": {"": [[0, 0, 1, "_CPPv46Sphinx", "Sphinx"]]}, "objnames": {"0": ["cpp", "class", "C++ class"]}, "objtypes": {"0": "cpp:class"}, "terms": {"a": 0, "c++": 0, "class": 0, "class.": 0, "description": 0, "engine": 0, "fixture.": 0, "generate": 0, "index": 0, "is": 0, "of": 0, "project": 0, "sample": 0, "search": 0, "sphinx": 0, "the": 0, "this": 0, "to": 0, "used": 0}, "titles": ["<no title>"], "titleterms": {}}) \ No newline at end of file diff --git a/tests/js/fixtures/index.multiterm.js b/tests/js/fixtures/index.multiterm.js index d1290e71827..dd88223a1fd 100644 --- a/tests/js/fixtures/index.multiterm.js +++ b/tests/js/fixtures/index.multiterm.js @@ -1,22 +1 @@ -Search.setIndex({ - alltitles: { - "Main Page": [[0, "main-page"]] - }, - docnames: [ - "index" - ], - filenames: [ - "index.rst" - ], - terms: { - main: 0, - page: 0 - }, - titles: [ - "Main Page" - ], - titleterms : { - main: 0, - page: 0 - } -}); +Search.setIndex({"alltitles": {"Main Page": [[0, "main-page"]]}, "docnames": ["index"], "envversion": {"sphinx": 61, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2}, "filenames": ["index.rst"], "indexentries": {}, "objects": {}, "objnames": {}, "objtypes": {}, "terms": {"a": [], "c++": [], "class": [], "class.": [], "description": [], "engine": [], "fixture.": [], "generate": [], "index": [], "is": [], "of": [], "project": [], "sample": [], "search": [], "sphinx": [], "the": [], "this": [], "to": [], "used": [], "welcom": 0}, "titles": ["Main Page"], "titleterms": {"main": 0, "page": 0}}) \ No newline at end of file diff --git a/tests/js/roots/cpp/conf.py b/tests/js/roots/cpp/conf.py new file mode 100644 index 00000000000..5d547e93e57 --- /dev/null +++ b/tests/js/roots/cpp/conf.py @@ -0,0 +1,14 @@ +from sphinx.search import SearchLanguage, languages + + +class NullStemmedLanguage(SearchLanguage): + + def split(self, input: str) -> list[str]: + return input.split() + + def stem(self, word: str) -> str: + return word.lower() + + +languages["xx"] = NullStemmedLanguage +html_search_language = "xx" diff --git a/tests/js/roots/cpp/index.rst b/tests/js/roots/cpp/index.rst new file mode 100644 index 00000000000..c6cb1e12e5a --- /dev/null +++ b/tests/js/roots/cpp/index.rst @@ -0,0 +1,5 @@ +This is a sample C++ project used to generate a search engine index fixture. + +.. cpp:class:: public Sphinx + + The description of Sphinx class. diff --git a/tests/js/roots/multiterm/conf.py b/tests/js/roots/multiterm/conf.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/js/roots/multiterm/index.rst b/tests/js/roots/multiterm/index.rst new file mode 100644 index 00000000000..2e9f4967893 --- /dev/null +++ b/tests/js/roots/multiterm/index.rst @@ -0,0 +1,4 @@ +Main Page +========= + +Welcome to the... main page! From e0bee37646dff04aa844a99d4a44c5a025d9ab3a Mon Sep 17 00:00:00 2001 From: James Addison Date: Fri, 15 Mar 2024 22:31:18 +0000 Subject: [PATCH 03/17] [tests] linting: add a ruff exclude filter for the JS fixture source roots --- .ruff.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/.ruff.toml b/.ruff.toml index 0d34a34b03e..fb84fefd11b 100644 --- a/.ruff.toml +++ b/.ruff.toml @@ -9,6 +9,7 @@ exclude = [ ".tox", ".venv", "tests/roots/*", + "tests/js/roots/*", "build/*", "doc/_build/*", "sphinx/search/*", From 4340bbed2d7f43b1fde1d798cc8db4ff4a2828fe Mon Sep 17 00:00:00 2001 From: James Addison Date: Sat, 16 Mar 2024 10:34:36 +0000 Subject: [PATCH 04/17] [tests] nitpick: reduce the changeset diff by retaining an index variable in test cases --- tests/js/searchtools.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/js/searchtools.js b/tests/js/searchtools.js index 47d5e6efb43..1ad589cf16b 100644 --- a/tests/js/searchtools.js +++ b/tests/js/searchtools.js @@ -12,11 +12,12 @@ describe('Basic html theme search', function() { it('should find "C++" when in index', function() { searchindex = loadFixture("index.cpp.js"); eval(searchindex); + index = Search._index; searchterms = ['c++']; excluded = []; - terms = Search._index.terms; - titleterms = Search._index.titleterms; + terms = index.terms; + titleterms = index.titleterms; hits = [[ "index", @@ -32,11 +33,12 @@ describe('Basic html theme search', function() { it('should be able to search for multiple terms', function() { searchindex = loadFixture("index.multiterm.js"); eval(searchindex); + index = Search._index; searchterms = ['main', 'page']; excluded = []; - terms = Search._index.terms; - titleterms = Search._index.titleterms; + terms = index.terms; + titleterms = index.titleterms; hits = [[ 'index', 'Main Page', From 40fc985bfdc55d4a7977fb5a000c76f03193c588 Mon Sep 17 00:00:00 2001 From: James Addison Date: Sat, 16 Mar 2024 10:41:51 +0000 Subject: [PATCH 05/17] Add CHANGES.rst entry --- CHANGES.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.rst b/CHANGES.rst index d49fdd9612e..973c4bb45d7 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -104,6 +104,7 @@ Testing * pytest: report the result of ``test_run_epubcheck`` as ``skipped`` instead of ``success`` when Java and/or the ``epubcheck.jar`` code are not available. +* karma: refactor HTML search tests to use fixtures generated by Sphinx. Release 7.2.6 (released Sep 13, 2023) ===================================== From 7e22d78d5f051d9f836c0076946beac2884d9ba1 Mon Sep 17 00:00:00 2001 From: James Addison Date: Sat, 16 Mar 2024 10:48:55 +0000 Subject: [PATCH 06/17] [tests] fixup: regenerate multiterm test search index --- tests/js/fixtures/index.multiterm.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/js/fixtures/index.multiterm.js b/tests/js/fixtures/index.multiterm.js index dd88223a1fd..282549de340 100644 --- a/tests/js/fixtures/index.multiterm.js +++ b/tests/js/fixtures/index.multiterm.js @@ -1 +1 @@ -Search.setIndex({"alltitles": {"Main Page": [[0, "main-page"]]}, "docnames": ["index"], "envversion": {"sphinx": 61, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2}, "filenames": ["index.rst"], "indexentries": {}, "objects": {}, "objnames": {}, "objtypes": {}, "terms": {"a": [], "c++": [], "class": [], "class.": [], "description": [], "engine": [], "fixture.": [], "generate": [], "index": [], "is": [], "of": [], "project": [], "sample": [], "search": [], "sphinx": [], "the": [], "this": [], "to": [], "used": [], "welcom": 0}, "titles": ["Main Page"], "titleterms": {"main": 0, "page": 0}}) \ No newline at end of file +Search.setIndex({"alltitles": {"Main Page": [[0, "main-page"]]}, "docnames": ["index"], "envversion": {"sphinx": 61, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2}, "filenames": ["index.rst"], "indexentries": {}, "objects": {}, "objnames": {}, "objtypes": {}, "terms": {"welcom": 0}, "titles": ["Main Page"], "titleterms": {"main": 0, "page": 0}}) \ No newline at end of file From 8f753a865ace1998085e4b1285562129eee80746 Mon Sep 17 00:00:00 2001 From: James Addison Date: Sat, 16 Mar 2024 10:52:21 +0000 Subject: [PATCH 07/17] [tests] refactor: use a separate index fixture directory per root --- karma.conf.js | 2 +- tests/js/fixtures/{index.cpp.js => cpp/searchindex.js} | 0 .../fixtures/{index.multiterm.js => multiterm/searchindex.js} | 0 tests/js/searchtools.js | 4 ++-- 4 files changed, 3 insertions(+), 3 deletions(-) rename tests/js/fixtures/{index.cpp.js => cpp/searchindex.js} (100%) rename tests/js/fixtures/{index.multiterm.js => multiterm/searchindex.js} (100%) diff --git a/karma.conf.js b/karma.conf.js index 5f20030596a..1ecdfd9fa7d 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -20,7 +20,7 @@ module.exports = function(config) { 'sphinx/themes/basic/static/searchtools.js', 'sphinx/themes/basic/static/sphinx_highlight.js', 'tests/js/*.js', - { pattern: 'tests/js/fixtures/*.js', included: false, served: true } + { pattern: 'tests/js/fixtures/**/*.js', included: false, served: true } ], diff --git a/tests/js/fixtures/index.cpp.js b/tests/js/fixtures/cpp/searchindex.js similarity index 100% rename from tests/js/fixtures/index.cpp.js rename to tests/js/fixtures/cpp/searchindex.js diff --git a/tests/js/fixtures/index.multiterm.js b/tests/js/fixtures/multiterm/searchindex.js similarity index 100% rename from tests/js/fixtures/index.multiterm.js rename to tests/js/fixtures/multiterm/searchindex.js diff --git a/tests/js/searchtools.js b/tests/js/searchtools.js index 1ad589cf16b..f994e5890b6 100644 --- a/tests/js/searchtools.js +++ b/tests/js/searchtools.js @@ -10,7 +10,7 @@ describe('Basic html theme search', function() { describe('terms search', function() { it('should find "C++" when in index', function() { - searchindex = loadFixture("index.cpp.js"); + searchindex = loadFixture("cpp/searchindex.js"); eval(searchindex); index = Search._index; @@ -31,7 +31,7 @@ describe('Basic html theme search', function() { }); it('should be able to search for multiple terms', function() { - searchindex = loadFixture("index.multiterm.js"); + searchindex = loadFixture("multiterm/searchindex.js"); eval(searchindex); index = Search._index; From 695037d9b77fed334e2c7c6e265922020a6b74d1 Mon Sep 17 00:00:00 2001 From: James Addison Date: Sat, 16 Mar 2024 12:22:21 +0000 Subject: [PATCH 08/17] [search] Refactor search code to improve testability --- sphinx/themes/basic/static/searchtools.js | 32 +++++++++++++++-------- tests/js/fixtures/cpp/searchindex.js | 2 +- tests/js/language_data.js | 26 ++++++++++++++++++ tests/js/roots/cpp/conf.py | 14 ---------- tests/js/searchtools.js | 25 ++++++------------ 5 files changed, 56 insertions(+), 43 deletions(-) create mode 100644 tests/js/language_data.js diff --git a/sphinx/themes/basic/static/searchtools.js b/sphinx/themes/basic/static/searchtools.js index 1197fa9f4a0..db25cfe41a3 100644 --- a/sphinx/themes/basic/static/searchtools.js +++ b/sphinx/themes/basic/static/searchtools.js @@ -250,16 +250,7 @@ const Search = { else Search.deferQuery(query); }, - /** - * execute search (requires search index to be loaded) - */ - query: (query) => { - const filenames = Search._index.filenames; - const docNames = Search._index.docnames; - const titles = Search._index.titles; - const allTitles = Search._index.alltitles; - const indexEntries = Search._index.indexentries; - + _parseQuery: (query) => { // stem the search terms and add them to the correct list const stemmer = new Stemmer(); const searchTerms = new Set(); @@ -295,6 +286,19 @@ const Search = { // console.info("required: ", [...searchTerms]); // console.info("excluded: ", [...excludedTerms]); + return [query, searchTerms, excludedTerms, highlightTerms, objectTerms]; + }, + + /** + * execute search (requires search index to be loaded) + */ + _performSearch: (query, searchTerms, excludedTerms, highlightTerms, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + const allTitles = Search._index.alltitles; + const indexEntries = Search._index.indexentries; + // array of [docname, title, anchor, descr, score, filename] let results = []; _removeChildren(document.getElementById("search-progress")); @@ -372,7 +376,13 @@ const Search = { return acc; }, []); - results = results.reverse(); + return results.reverse(); + }, + + query: (query) => { + + const searchTerms = Search._parseQuery(query); + const results = Search._performSearch(...searchTerms); // for debugging //Search.lastresults = results.slice(); // a copy diff --git a/tests/js/fixtures/cpp/searchindex.js b/tests/js/fixtures/cpp/searchindex.js index 8be181211a9..3a42936c501 100644 --- a/tests/js/fixtures/cpp/searchindex.js +++ b/tests/js/fixtures/cpp/searchindex.js @@ -1 +1 @@ -Search.setIndex({"alltitles": {}, "docnames": ["index"], "envversion": {"sphinx": 61, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2}, "filenames": ["index.rst"], "indexentries": {"sphinx (c++ class)": [[0, "_CPPv46Sphinx"]]}, "objects": {"": [[0, 0, 1, "_CPPv46Sphinx", "Sphinx"]]}, "objnames": {"0": ["cpp", "class", "C++ class"]}, "objtypes": {"0": "cpp:class"}, "terms": {"a": 0, "c++": 0, "class": 0, "class.": 0, "description": 0, "engine": 0, "fixture.": 0, "generate": 0, "index": 0, "is": 0, "of": 0, "project": 0, "sample": 0, "search": 0, "sphinx": 0, "the": 0, "this": 0, "to": 0, "used": 0}, "titles": ["<no title>"], "titleterms": {}}) \ No newline at end of file +Search.setIndex({"alltitles": {}, "docnames": ["index"], "envversion": {"sphinx": 61, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2}, "filenames": ["index.rst"], "indexentries": {"sphinx (c++ class)": [[0, "_CPPv46Sphinx"]]}, "objects": {"": [[0, 0, 1, "_CPPv46Sphinx", "Sphinx"]]}, "objnames": {"0": ["cpp", "class", "C++ class"]}, "objtypes": {"0": "cpp:class"}, "terms": {"The": 0, "a": [], "c": 0, "c++": [], "class": 0, "class.": [], "descript": 0, "description": [], "engin": 0, "engine": [], "fixtur": 0, "fixture.": [], "gener": 0, "generate": [], "i": 0, "index": 0, "is": [], "of": [], "project": 0, "sampl": 0, "sample": [], "search": 0, "sphinx": 0, "the": [], "thi": 0, "this": [], "to": [], "us": 0, "used": []}, "titles": ["<no title>"], "titleterms": {}}) \ No newline at end of file diff --git a/tests/js/language_data.js b/tests/js/language_data.js new file mode 100644 index 00000000000..db395c75dc0 --- /dev/null +++ b/tests/js/language_data.js @@ -0,0 +1,26 @@ +/* + * language_data.js + * ~~~~~~~~~~~~~~~~ + * + * This script contains the language-specific data used by searchtools.js, + * namely the list of stopwords, stemmer, scorer and splitter. + * + * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +var stopwords = []; + + +/* Non-minified version is copied as a separate JS file, is available */ + +/** + * Dummy stemmer for languages without stemming rules. + */ +var Stemmer = function() { + this.stemWord = function(w) { + return w; + } +} + diff --git a/tests/js/roots/cpp/conf.py b/tests/js/roots/cpp/conf.py index 5d547e93e57..e69de29bb2d 100644 --- a/tests/js/roots/cpp/conf.py +++ b/tests/js/roots/cpp/conf.py @@ -1,14 +0,0 @@ -from sphinx.search import SearchLanguage, languages - - -class NullStemmedLanguage(SearchLanguage): - - def split(self, input: str) -> list[str]: - return input.split() - - def stem(self, word: str) -> str: - return word.lower() - - -languages["xx"] = NullStemmedLanguage -html_search_language = "xx" diff --git a/tests/js/searchtools.js b/tests/js/searchtools.js index f994e5890b6..e1bd0827b88 100644 --- a/tests/js/searchtools.js +++ b/tests/js/searchtools.js @@ -10,14 +10,9 @@ describe('Basic html theme search', function() { describe('terms search', function() { it('should find "C++" when in index', function() { - searchindex = loadFixture("cpp/searchindex.js"); - eval(searchindex); - index = Search._index; + eval(loadFixture("cpp/searchindex.js")); - searchterms = ['c++']; - excluded = []; - terms = index.terms; - titleterms = index.titleterms; + searchTerms = Search._parseQuery('C++'); hits = [[ "index", @@ -27,18 +22,14 @@ describe('Basic html theme search', function() { 5, "index.rst" ]]; - expect(Search.performTermsSearch(searchterms, excluded, terms, titleterms)).toEqual(hits); + expect(Search._performSearch(...searchTerms)).toEqual(hits); }); it('should be able to search for multiple terms', function() { - searchindex = loadFixture("multiterm/searchindex.js"); - eval(searchindex); - index = Search._index; - - searchterms = ['main', 'page']; - excluded = []; - terms = index.terms; - titleterms = index.titleterms; + eval(loadFixture("multiterm/searchindex.js")); + + searchTerms = Search._parseQuery('main page'); + hits = [[ 'index', 'Main Page', @@ -46,7 +37,7 @@ describe('Basic html theme search', function() { null, 15, 'index.rst']]; - expect(Search.performTermsSearch(searchterms, excluded, terms, titleterms)).toEqual(hits); + expect(Search._performSearch(...searchTerms)).toEqual(hits); }); }); From 58b5e901dbd9be52fc139fd0d8ef898d9756e9a9 Mon Sep 17 00:00:00 2001 From: James Addison Date: Sat, 16 Mar 2024 12:48:08 +0000 Subject: [PATCH 09/17] [tests] expect duplicate result due to #11961 --- tests/js/searchtools.js | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/tests/js/searchtools.js b/tests/js/searchtools.js index e1bd0827b88..5540be1f0de 100644 --- a/tests/js/searchtools.js +++ b/tests/js/searchtools.js @@ -30,13 +30,25 @@ describe('Basic html theme search', function() { searchTerms = Search._parseQuery('main page'); - hits = [[ - 'index', - 'Main Page', - '', - null, - 15, - 'index.rst']]; + // fixme: duplicate result due to https://github.com/sphinx-doc/sphinx/issues/11961 + hits = [ + [ + 'index', + 'Main Page', + '', + null, + 15, + 'index.rst' + ], + [ + 'index', + 'Main Page', + '#main-page', + null, + 100, + 'index.rst' + ] + ]; expect(Search._performSearch(...searchTerms)).toEqual(hits); }); From c37bb53bf61dec291aa16bedb9d364718130b0db Mon Sep 17 00:00:00 2001 From: James Addison Date: Sat, 16 Mar 2024 15:08:24 +0000 Subject: [PATCH 10/17] [tests] run 'js-beautify -r ...' on each searchindex.js file --- tests/js/fixtures/cpp/searchindex.js | 58 +++++++++++++++++++++- tests/js/fixtures/multiterm/searchindex.js | 35 ++++++++++++- 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/tests/js/fixtures/cpp/searchindex.js b/tests/js/fixtures/cpp/searchindex.js index 8be181211a9..a73122672c2 100644 --- a/tests/js/fixtures/cpp/searchindex.js +++ b/tests/js/fixtures/cpp/searchindex.js @@ -1 +1,57 @@ -Search.setIndex({"alltitles": {}, "docnames": ["index"], "envversion": {"sphinx": 61, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2}, "filenames": ["index.rst"], "indexentries": {"sphinx (c++ class)": [[0, "_CPPv46Sphinx"]]}, "objects": {"": [[0, 0, 1, "_CPPv46Sphinx", "Sphinx"]]}, "objnames": {"0": ["cpp", "class", "C++ class"]}, "objtypes": {"0": "cpp:class"}, "terms": {"a": 0, "c++": 0, "class": 0, "class.": 0, "description": 0, "engine": 0, "fixture.": 0, "generate": 0, "index": 0, "is": 0, "of": 0, "project": 0, "sample": 0, "search": 0, "sphinx": 0, "the": 0, "this": 0, "to": 0, "used": 0}, "titles": ["<no title>"], "titleterms": {}}) \ No newline at end of file +Search.setIndex({ + "alltitles": {}, + "docnames": ["index"], + "envversion": { + "sphinx": 61, + "sphinx.domains.c": 3, + "sphinx.domains.changeset": 1, + "sphinx.domains.citation": 1, + "sphinx.domains.cpp": 9, + "sphinx.domains.index": 1, + "sphinx.domains.javascript": 3, + "sphinx.domains.math": 2, + "sphinx.domains.python": 4, + "sphinx.domains.rst": 2, + "sphinx.domains.std": 2 + }, + "filenames": ["index.rst"], + "indexentries": { + "sphinx (c++ class)": [ + [0, "_CPPv46Sphinx"] + ] + }, + "objects": { + "": [ + [0, 0, 1, "_CPPv46Sphinx", "Sphinx"] + ] + }, + "objnames": { + "0": ["cpp", "class", "C++ class"] + }, + "objtypes": { + "0": "cpp:class" + }, + "terms": { + "a": 0, + "c++": 0, + "class": 0, + "class.": 0, + "description": 0, + "engine": 0, + "fixture.": 0, + "generate": 0, + "index": 0, + "is": 0, + "of": 0, + "project": 0, + "sample": 0, + "search": 0, + "sphinx": 0, + "the": 0, + "this": 0, + "to": 0, + "used": 0 + }, + "titles": ["<no title>"], + "titleterms": {} +}) \ No newline at end of file diff --git a/tests/js/fixtures/multiterm/searchindex.js b/tests/js/fixtures/multiterm/searchindex.js index 282549de340..976679c9a04 100644 --- a/tests/js/fixtures/multiterm/searchindex.js +++ b/tests/js/fixtures/multiterm/searchindex.js @@ -1 +1,34 @@ -Search.setIndex({"alltitles": {"Main Page": [[0, "main-page"]]}, "docnames": ["index"], "envversion": {"sphinx": 61, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2}, "filenames": ["index.rst"], "indexentries": {}, "objects": {}, "objnames": {}, "objtypes": {}, "terms": {"welcom": 0}, "titles": ["Main Page"], "titleterms": {"main": 0, "page": 0}}) \ No newline at end of file +Search.setIndex({ + "alltitles": { + "Main Page": [ + [0, "main-page"] + ] + }, + "docnames": ["index"], + "envversion": { + "sphinx": 61, + "sphinx.domains.c": 3, + "sphinx.domains.changeset": 1, + "sphinx.domains.citation": 1, + "sphinx.domains.cpp": 9, + "sphinx.domains.index": 1, + "sphinx.domains.javascript": 3, + "sphinx.domains.math": 2, + "sphinx.domains.python": 4, + "sphinx.domains.rst": 2, + "sphinx.domains.std": 2 + }, + "filenames": ["index.rst"], + "indexentries": {}, + "objects": {}, + "objnames": {}, + "objtypes": {}, + "terms": { + "welcom": 0 + }, + "titles": ["Main Page"], + "titleterms": { + "main": 0, + "page": 0 + } +}) \ No newline at end of file From 8ac1b6ccdaea6ba52eae214c52d29bf904380fe9 Mon Sep 17 00:00:00 2001 From: James Addison Date: Sat, 16 Mar 2024 15:13:46 +0000 Subject: [PATCH 11/17] [tests] Fixup: regenerate cpp searchindex.js --- tests/js/fixtures/cpp/searchindex.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/js/fixtures/cpp/searchindex.js b/tests/js/fixtures/cpp/searchindex.js index 3a42936c501..e110a2853e4 100644 --- a/tests/js/fixtures/cpp/searchindex.js +++ b/tests/js/fixtures/cpp/searchindex.js @@ -1 +1 @@ -Search.setIndex({"alltitles": {}, "docnames": ["index"], "envversion": {"sphinx": 61, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2}, "filenames": ["index.rst"], "indexentries": {"sphinx (c++ class)": [[0, "_CPPv46Sphinx"]]}, "objects": {"": [[0, 0, 1, "_CPPv46Sphinx", "Sphinx"]]}, "objnames": {"0": ["cpp", "class", "C++ class"]}, "objtypes": {"0": "cpp:class"}, "terms": {"The": 0, "a": [], "c": 0, "c++": [], "class": 0, "class.": [], "descript": 0, "description": [], "engin": 0, "engine": [], "fixtur": 0, "fixture.": [], "gener": 0, "generate": [], "i": 0, "index": 0, "is": [], "of": [], "project": 0, "sampl": 0, "sample": [], "search": 0, "sphinx": 0, "the": [], "thi": 0, "this": [], "to": [], "us": 0, "used": []}, "titles": ["<no title>"], "titleterms": {}}) \ No newline at end of file +Search.setIndex({"alltitles": {}, "docnames": ["index"], "envversion": {"sphinx": 61, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2}, "filenames": ["index.rst"], "indexentries": {"sphinx (c++ class)": [[0, "_CPPv46Sphinx"]]}, "objects": {"": [[0, 0, 1, "_CPPv46Sphinx", "Sphinx"]]}, "objnames": {"0": ["cpp", "class", "C++ class"]}, "objtypes": {"0": "cpp:class"}, "terms": {"The": 0, "c": 0, "class": 0, "descript": 0, "engin": 0, "fixtur": 0, "gener": 0, "i": 0, "index": 0, "project": 0, "sampl": 0, "search": 0, "sphinx": 0, "thi": 0, "us": 0}, "titles": ["<no title>"], "titleterms": {}}) \ No newline at end of file From fbaff49c264640caefd190db3afc10b4cea6e406 Mon Sep 17 00:00:00 2001 From: James Addison Date: Sat, 16 Mar 2024 15:59:31 +0000 Subject: [PATCH 12/17] [utils] Add script to regenerate JavaScript test fixtures --- utils/generate_js_fixtures.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100755 utils/generate_js_fixtures.py diff --git a/utils/generate_js_fixtures.py b/utils/generate_js_fixtures.py new file mode 100755 index 00000000000..d9afa029037 --- /dev/null +++ b/utils/generate_js_fixtures.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 + +import subprocess +from pathlib import Path + +SPHINX_ROOT = Path(__file__).resolve().parents[1] +TEST_JS_FIXTURES = SPHINX_ROOT / "tests" / "js" / "fixtures" +TEST_JS_ROOTS = SPHINX_ROOT / "tests" / "js" / "roots" + + +def build(srcdir: Path) -> None: + cmd = ("sphinx-build", "-E", "-q", "-b", "html", f"{srcdir}", f"{srcdir}/build") + subprocess.run(cmd, check=True, capture_output=True) + + +def beautify(filename: Path) -> None: + cmd = ("js-beautify", "-r", filename) + subprocess.run(cmd, check=True, capture_output=True) + + +for directory in TEST_JS_ROOTS.iterdir(): + searchindex = directory / "build" / "searchindex.js" + destination = TEST_JS_FIXTURES / directory.name / "searchindex.js" + + print(f"Building {directory} ... ", end="") + build(directory) + print("done") + + print(f"Beautifying {searchindex} ... ", end="") + beautify(searchindex) + print("done") + + print(f"Moving {searchindex} to {destination} ... ", end="") + searchindex.replace(destination) + print("done") From d619a5211a5b863896996e71ee92ffb7f60866d5 Mon Sep 17 00:00:00 2001 From: James Addison Date: Sat, 16 Mar 2024 16:38:15 +0000 Subject: [PATCH 13/17] [tests] nitpick: relocate project-related JavaScript files away from directory containing test case files --- karma.conf.js | 3 ++- tests/js/{ => project}/documentation_options.js | 0 tests/js/{ => project}/language_data.js | 0 3 files changed, 2 insertions(+), 1 deletion(-) rename tests/js/{ => project}/documentation_options.js (100%) rename tests/js/{ => project}/language_data.js (100%) diff --git a/karma.conf.js b/karma.conf.js index 1ecdfd9fa7d..b2bd6d2350e 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -15,7 +15,8 @@ module.exports = function(config) { // list of files / patterns to load in the browser files: [ - 'tests/js/documentation_options.js', + 'tests/js/project/documentation_options.js', + 'tests/js/project/language_data.js', 'sphinx/themes/basic/static/doctools.js', 'sphinx/themes/basic/static/searchtools.js', 'sphinx/themes/basic/static/sphinx_highlight.js', diff --git a/tests/js/documentation_options.js b/tests/js/project/documentation_options.js similarity index 100% rename from tests/js/documentation_options.js rename to tests/js/project/documentation_options.js diff --git a/tests/js/language_data.js b/tests/js/project/language_data.js similarity index 100% rename from tests/js/language_data.js rename to tests/js/project/language_data.js From ee4316d80bcc93c230b410edf508c2f5e70571a4 Mon Sep 17 00:00:00 2001 From: James Addison Date: Mon, 18 Mar 2024 19:32:37 +0000 Subject: [PATCH 14/17] [tests] Regenerate test fixtures by running 'python utils/generate_js_fixtures.py' --- tests/js/fixtures/cpp/searchindex.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/js/fixtures/cpp/searchindex.js b/tests/js/fixtures/cpp/searchindex.js index 3948913c309..17f1ae8d9b8 100644 --- a/tests/js/fixtures/cpp/searchindex.js +++ b/tests/js/fixtures/cpp/searchindex.js @@ -17,7 +17,7 @@ Search.setIndex({ "filenames": ["index.rst"], "indexentries": { "sphinx (c++ class)": [ - [0, "_CPPv46Sphinx"] + [0, "_CPPv46Sphinx", false] ] }, "objects": { From 0bc558abddc362be3e714920ac73c6b045217a30 Mon Sep 17 00:00:00 2001 From: James Addison Date: Sat, 16 Mar 2024 15:59:31 +0000 Subject: [PATCH 15/17] [utils] Add script to regenerate JavaScript test fixtures --- utils/generate_js_fixtures.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100755 utils/generate_js_fixtures.py diff --git a/utils/generate_js_fixtures.py b/utils/generate_js_fixtures.py new file mode 100755 index 00000000000..d9afa029037 --- /dev/null +++ b/utils/generate_js_fixtures.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 + +import subprocess +from pathlib import Path + +SPHINX_ROOT = Path(__file__).resolve().parents[1] +TEST_JS_FIXTURES = SPHINX_ROOT / "tests" / "js" / "fixtures" +TEST_JS_ROOTS = SPHINX_ROOT / "tests" / "js" / "roots" + + +def build(srcdir: Path) -> None: + cmd = ("sphinx-build", "-E", "-q", "-b", "html", f"{srcdir}", f"{srcdir}/build") + subprocess.run(cmd, check=True, capture_output=True) + + +def beautify(filename: Path) -> None: + cmd = ("js-beautify", "-r", filename) + subprocess.run(cmd, check=True, capture_output=True) + + +for directory in TEST_JS_ROOTS.iterdir(): + searchindex = directory / "build" / "searchindex.js" + destination = TEST_JS_FIXTURES / directory.name / "searchindex.js" + + print(f"Building {directory} ... ", end="") + build(directory) + print("done") + + print(f"Beautifying {searchindex} ... ", end="") + beautify(searchindex) + print("done") + + print(f"Moving {searchindex} to {destination} ... ", end="") + searchindex.replace(destination) + print("done") From a74bc156d5f10ce3e5f87cfc56f51d7100976e9b Mon Sep 17 00:00:00 2001 From: James Addison Date: Fri, 22 Mar 2024 13:44:33 +0000 Subject: [PATCH 16/17] [utils] Remove beautification step for generated searchindex.js files. Ref: https://github.com/sphinx-doc/sphinx/pull/12102#discussion_r1535606662 --- utils/generate_js_fixtures.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/utils/generate_js_fixtures.py b/utils/generate_js_fixtures.py index d9afa029037..beb5254393a 100755 --- a/utils/generate_js_fixtures.py +++ b/utils/generate_js_fixtures.py @@ -26,10 +26,6 @@ def beautify(filename: Path) -> None: build(directory) print("done") - print(f"Beautifying {searchindex} ... ", end="") - beautify(searchindex) - print("done") - print(f"Moving {searchindex} to {destination} ... ", end="") searchindex.replace(destination) print("done") From 68a6504c8922652a6c389f0934d3958b0810e26d Mon Sep 17 00:00:00 2001 From: James Addison Date: Fri, 22 Mar 2024 13:50:47 +0000 Subject: [PATCH 17/17] [tests] Regenerate searchindex.js files. --- tests/js/fixtures/cpp/searchindex.js | 54 +--------------------- tests/js/fixtures/multiterm/searchindex.js | 35 +------------- 2 files changed, 2 insertions(+), 87 deletions(-) diff --git a/tests/js/fixtures/cpp/searchindex.js b/tests/js/fixtures/cpp/searchindex.js index 17f1ae8d9b8..b829f7cc320 100644 --- a/tests/js/fixtures/cpp/searchindex.js +++ b/tests/js/fixtures/cpp/searchindex.js @@ -1,53 +1 @@ -Search.setIndex({ - "alltitles": {}, - "docnames": ["index"], - "envversion": { - "sphinx": 61, - "sphinx.domains.c": 3, - "sphinx.domains.changeset": 1, - "sphinx.domains.citation": 1, - "sphinx.domains.cpp": 9, - "sphinx.domains.index": 1, - "sphinx.domains.javascript": 3, - "sphinx.domains.math": 2, - "sphinx.domains.python": 4, - "sphinx.domains.rst": 2, - "sphinx.domains.std": 2 - }, - "filenames": ["index.rst"], - "indexentries": { - "sphinx (c++ class)": [ - [0, "_CPPv46Sphinx", false] - ] - }, - "objects": { - "": [ - [0, 0, 1, "_CPPv46Sphinx", "Sphinx"] - ] - }, - "objnames": { - "0": ["cpp", "class", "C++ class"] - }, - "objtypes": { - "0": "cpp:class" - }, - "terms": { - "The": 0, - "c": 0, - "class": 0, - "descript": 0, - "engin": 0, - "fixtur": 0, - "gener": 0, - "i": 0, - "index": 0, - "project": 0, - "sampl": 0, - "search": 0, - "sphinx": 0, - "thi": 0, - "us": 0 - }, - "titles": ["<no title>"], - "titleterms": {} -}) \ No newline at end of file +Search.setIndex({"alltitles": {}, "docnames": ["index"], "envversion": {"sphinx": 61, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2}, "filenames": ["index.rst"], "indexentries": {"sphinx (c++ class)": [[0, "_CPPv46Sphinx", false]]}, "objects": {"": [[0, 0, 1, "_CPPv46Sphinx", "Sphinx"]]}, "objnames": {"0": ["cpp", "class", "C++ class"]}, "objtypes": {"0": "cpp:class"}, "terms": {"The": 0, "c": 0, "class": 0, "descript": 0, "engin": 0, "fixtur": 0, "gener": 0, "i": 0, "index": 0, "project": 0, "sampl": 0, "search": 0, "sphinx": 0, "thi": 0, "us": 0}, "titles": ["<no title>"], "titleterms": {}}) \ No newline at end of file diff --git a/tests/js/fixtures/multiterm/searchindex.js b/tests/js/fixtures/multiterm/searchindex.js index 976679c9a04..282549de340 100644 --- a/tests/js/fixtures/multiterm/searchindex.js +++ b/tests/js/fixtures/multiterm/searchindex.js @@ -1,34 +1 @@ -Search.setIndex({ - "alltitles": { - "Main Page": [ - [0, "main-page"] - ] - }, - "docnames": ["index"], - "envversion": { - "sphinx": 61, - "sphinx.domains.c": 3, - "sphinx.domains.changeset": 1, - "sphinx.domains.citation": 1, - "sphinx.domains.cpp": 9, - "sphinx.domains.index": 1, - "sphinx.domains.javascript": 3, - "sphinx.domains.math": 2, - "sphinx.domains.python": 4, - "sphinx.domains.rst": 2, - "sphinx.domains.std": 2 - }, - "filenames": ["index.rst"], - "indexentries": {}, - "objects": {}, - "objnames": {}, - "objtypes": {}, - "terms": { - "welcom": 0 - }, - "titles": ["Main Page"], - "titleterms": { - "main": 0, - "page": 0 - } -}) \ No newline at end of file +Search.setIndex({"alltitles": {"Main Page": [[0, "main-page"]]}, "docnames": ["index"], "envversion": {"sphinx": 61, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2}, "filenames": ["index.rst"], "indexentries": {}, "objects": {}, "objnames": {}, "objtypes": {}, "terms": {"welcom": 0}, "titles": ["Main Page"], "titleterms": {"main": 0, "page": 0}}) \ No newline at end of file