From 8bade66eedbb6f41863e081d40d47c6b52dda4c3 Mon Sep 17 00:00:00 2001 From: Michael Lyons Date: Tue, 11 Nov 2025 10:57:06 -0500 Subject: [PATCH 1/7] Add basic index sanity tests See #5 Tests two criteria from #12 --- .github/workflows/build.yml | 1 + Makefile | 4 +++ test/test_docset.py | 55 +++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 test/test_docset.py diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3bea1bf..fbbabdd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,6 +29,7 @@ jobs: - name: Build the docset run: | make + make test make zip - name: Upload the ST docset diff --git a/Makefile b/Makefile index 76cab58..0f20bcf 100644 --- a/Makefile +++ b/Makefile @@ -49,5 +49,9 @@ zip: cd $(out_folder) && tar -czvf $(st_docset).tgz $(st_docset) cd $(out_folder) && tar -czvf $(sm_docset).tgz $(sm_docset) +.PHONY: test +test: + cd test && python -m unittest + install-linux: cp -r $(out_folder)/* $(install_path_linux) diff --git a/test/test_docset.py b/test/test_docset.py new file mode 100644 index 0000000..e9e74f0 --- /dev/null +++ b/test/test_docset.py @@ -0,0 +1,55 @@ +import unittest +import sqlite3 + +from abc import ABC + + +class DocsetTestCaseBase(ABC, unittest.TestCase): + NAME = None + SQLITE_PATH_FMT = '../out/{}/Contents/Resources/docSet.dsidx' + + @classmethod + def setUpClass(cls): + cls.con = sqlite3.connect(cls.SQLITE_PATH_FMT.format(cls.NAME)) + cls.cur = cls.con.cursor() + + @classmethod + def tearDownClass(cls): + cls.con.close() + + def test_no_empty_aliases(self): + """The docset index must not contain empty entries""" + sql = ''' + SELECT * + FROM searchIndex + WHERE name = '' + ''' + res = self.cur.execute(sql) + self.assertFalse(res.fetchall()) + + def test_no_newline_aliases(self): + """The docset index must not contain entries with newlines in them""" + sql = ''' + SELECT * + FROM searchIndex + WHERE name LIKE '%\n%' + ''' + res = self.cur.execute(sql) + self.assertFalse(res.fetchall()) + + @unittest.skip('Not implemented') + def test_no_broken_paths(self): + """The docset index must not contain broken paths""" + pass + + +class SublimeMergeDocsetTestCase(DocsetTestCaseBase): + NAME = 'sublime-merge.docset' + + +class SublimeTextDocsetTestCase(DocsetTestCaseBase): + NAME = 'sublime-text.docset' + + +# Don't test the base class directly +del DocsetTestCaseBase From 885ae702a65a3b81e1ac00f5acbb0c397e15132e Mon Sep 17 00:00:00 2001 From: Michael Lyons Date: Tue, 11 Nov 2025 11:37:49 -0500 Subject: [PATCH 2/7] Test dashing link format --- test/test_docset.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/test_docset.py b/test/test_docset.py index e9e74f0..6028746 100644 --- a/test/test_docset.py +++ b/test/test_docset.py @@ -42,6 +42,16 @@ def test_no_broken_paths(self): """The docset index must not contain broken paths""" pass + def test_paths_are_autolinks(self): + """Sanity check dashing format""" + sql = ''' + SELECT * + FROM searchIndex + WHERE path NOT LIKE 'docs/%.html#autolink-%' + ''' + res = self.cur.execute(sql) + self.assertFalse(res.fetchall()) + class SublimeMergeDocsetTestCase(DocsetTestCaseBase): NAME = 'sublime-merge.docset' From 21da8161d546098ce45c2b85834433b8d5c8db53 Mon Sep 17 00:00:00 2001 From: Michael Lyons Date: Tue, 11 Nov 2025 11:38:29 -0500 Subject: [PATCH 3/7] Test a single page's index --- test/test_docset.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/test/test_docset.py b/test/test_docset.py index 6028746..c9f8ebd 100644 --- a/test/test_docset.py +++ b/test/test_docset.py @@ -2,6 +2,7 @@ import sqlite3 from abc import ABC +from collections import defaultdict class DocsetTestCaseBase(ABC, unittest.TestCase): @@ -60,6 +61,39 @@ class SublimeMergeDocsetTestCase(DocsetTestCaseBase): class SublimeTextDocsetTestCase(DocsetTestCaseBase): NAME = 'sublime-text.docset' + def test_api_reference(self): + contains = [ + ('Guide', 'API Reference'), + ('Module', 'sublime'), + ('Module', 'sublime_plugin'), + ('Class', 'sublime.Window'), + ('Type', 'sublime.Kind'), + ('Type', 'sublime.Event'), + ('Class', 'sublime_plugin.EventListener'), + ('Method', 'sublime_plugin.ViewEventListener.on_activated'), + ('Function', 'sublime.cache_path'), + ('Attribute', 'sublime.KindId.COLOR_YELLOWISH'), + ('Attribute', 'sublime.RegionFlags.DRAW_EMPTY_AS_OVERWRITE'), + ] + sql = ''' + SELECT type, name + FROM searchIndex + WHERE path LIKE 'docs/api_reference.html#%' + ''' + res = self.cur.execute(sql) + items = res.fetchall() + + lookup = defaultdict(list) + for check in contains: + lookup[check[1]].append(check[0]) + + for pair in contains: + self.assertIn(pair, items) + + ds_type, ds_term = pair + lookup_result = lookup[ds_term][:] + self.assertFalse(lookup_result.remove(ds_type)) + # Don't test the base class directly del DocsetTestCaseBase From 1c02a589d0a34ec1a89fa4eb89ade15bdb35b8b6 Mon Sep 17 00:00:00 2001 From: Michael Lyons Date: Tue, 11 Nov 2025 11:48:47 -0500 Subject: [PATCH 4/7] Refactor page index test --- test/test_docset.py | 46 +++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/test/test_docset.py b/test/test_docset.py index c9f8ebd..e4d98a3 100644 --- a/test/test_docset.py +++ b/test/test_docset.py @@ -53,6 +53,33 @@ def test_paths_are_autolinks(self): res = self.cur.execute(sql) self.assertFalse(res.fetchall()) + def _test_a_doc_page_index( + self, path: str, + contains_strict: list[tuple[str,str]], + contains_lenient: list[tuple[str,str]] | None = None, + ): + sql = f''' + SELECT type, name + FROM searchIndex + WHERE path LIKE '{path}#%' + ''' + res = self.cur.execute(sql) + items = res.fetchall() + + for pair in contains_lenient or []: + self.assertIn(pair, items) + + lookup = defaultdict(list) + for check in contains_strict: + lookup[check[1]].append(check[0]) + + for pair in contains_strict: + self.assertIn(pair, items) + + ds_type, ds_term = pair + lookup_result = lookup[ds_term][:] + self.assertFalse(lookup_result.remove(ds_type)) + class SublimeMergeDocsetTestCase(DocsetTestCaseBase): NAME = 'sublime-merge.docset' @@ -75,24 +102,7 @@ def test_api_reference(self): ('Attribute', 'sublime.KindId.COLOR_YELLOWISH'), ('Attribute', 'sublime.RegionFlags.DRAW_EMPTY_AS_OVERWRITE'), ] - sql = ''' - SELECT type, name - FROM searchIndex - WHERE path LIKE 'docs/api_reference.html#%' - ''' - res = self.cur.execute(sql) - items = res.fetchall() - - lookup = defaultdict(list) - for check in contains: - lookup[check[1]].append(check[0]) - - for pair in contains: - self.assertIn(pair, items) - - ds_type, ds_term = pair - lookup_result = lookup[ds_term][:] - self.assertFalse(lookup_result.remove(ds_type)) + self._test_a_doc_page_index('docs/api_reference.html', contains) # Don't test the base class directly From 9b5a9d253c3465365f3cb838686154554b11c6bb Mon Sep 17 00:00:00 2001 From: Michael Lyons Date: Tue, 11 Nov 2025 12:45:44 -0500 Subject: [PATCH 5/7] Fix newlines in docset index --- Makefile | 11 +++++------ fix_index.py | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 6 deletions(-) create mode 100644 fix_index.py diff --git a/Makefile b/Makefile index 0f20bcf..adcf6c8 100644 --- a/Makefile +++ b/Makefile @@ -17,13 +17,9 @@ sm_docset := sublime-merge.docset sm_built_path := $(sm_site)/$(sm_docset) .PHONY: all -all: clean pre-build build +all: clean pre-build build post-build -.PHONY: fix -pre-build: fix-html - -.PHONY: fix-html -fix-html: +pre-build: python fix_html.py build: @@ -38,6 +34,9 @@ build: cd $(sm_site) && dashing build mv $(sm_built_path) $(out_folder) +post-build: + python fix_index.py + .PHONY: clean clean: [ -d "$(out_folder)" ] && rm -r $(out_folder) || true diff --git a/fix_index.py b/fix_index.py new file mode 100644 index 0000000..c2de483 --- /dev/null +++ b/fix_index.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 + +""" +Tweaks the docset SQLite index after creation +""" +import sys +import sqlite3 + +SQLITE_PATH_FMT = 'out/{}/Contents/Resources/docSet.dsidx' +DOCSET_FIXES = { + 'sublime-text.docset': [ + ('docs/distraction_free.html', + 'Packages/Default/Distraction\nFree.sublime-settings', + 'Packages/Default/Distraction Free.sublime-settings',), + ('docs/distraction_free.html', + 'Packages/User/Distraction\nFree.sublime-settings', + 'Packages/User/Distraction Free.sublime-settings',), + ('docs/syntax.html', + ' SYNTAX\nTEST ""', + ' SYNTAX TEST ""', ), + ], + 'sublime-merge.docset': [] +} + + +def main(): + for docset in DOCSET_FIXES: + con = sqlite3.connect(SQLITE_PATH_FMT.format(docset)) + cur = con.cursor() + + for fix in DOCSET_FIXES[docset]: + path, old_name, new_name = fix + data = { + 'old_name': old_name, + 'new_name': new_name, + 'path_like': path + '#%', + } + + cur.execute( + ''' + UPDATE searchIndex + SET name = :new_name + WHERE name = :old_name + AND path LIKE :path_like + ''', + data + ) + con.commit() + con.close() + + +if __name__ == '__main__': + sys.exit(main()) From 0c9664a5a8d606e60cfa8ecb20c9b9a675f78793 Mon Sep 17 00:00:00 2001 From: Michael Lyons Date: Tue, 11 Nov 2025 12:46:18 -0500 Subject: [PATCH 6/7] Test every build Why not? --- .github/workflows/build.yml | 1 - Makefile | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fbbabdd..3bea1bf 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,7 +29,6 @@ jobs: - name: Build the docset run: | make - make test make zip - name: Upload the ST docset diff --git a/Makefile b/Makefile index adcf6c8..e017978 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ sm_docset := sublime-merge.docset sm_built_path := $(sm_site)/$(sm_docset) .PHONY: all -all: clean pre-build build post-build +all: clean pre-build build post-build test pre-build: python fix_html.py From e8a0462020996b1c9cbb54cdd88e1aca0c93da44 Mon Sep 17 00:00:00 2001 From: Michael Lyons Date: Tue, 11 Nov 2025 12:46:43 -0500 Subject: [PATCH 7/7] Test Git Integration page --- sublime-text-dashing.yml | 2 +- test/test_docset.py | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/sublime-text-dashing.yml b/sublime-text-dashing.yml index 52bb0c5..b4ece23 100644 --- a/sublime-text-dashing.yml +++ b/sublime-text-dashing.yml @@ -31,7 +31,7 @@ selectors: # Git Status badges '#status-badge-key .badges li': - type: Enum + type: Attribute matchpath: '/git_integration\.html$' # Commands and menus diff --git a/test/test_docset.py b/test/test_docset.py index e4d98a3..beff2bb 100644 --- a/test/test_docset.py +++ b/test/test_docset.py @@ -88,6 +88,16 @@ class SublimeMergeDocsetTestCase(DocsetTestCaseBase): class SublimeTextDocsetTestCase(DocsetTestCaseBase): NAME = 'sublime-text.docset' + def test_git_integration(self): + contains = [ + ('Guide', 'Git Integration'), + ('Attribute', 'Staged Modification'), + ('Section', 'Diff Markers'), + ('Command', 'Open Git Repository…'), + ('Command', 'Sublime Merge: Folder History'), + ] + self._test_a_doc_page_index('docs/git_integration.html', contains) + def test_api_reference(self): contains = [ ('Guide', 'API Reference'),