"""The search of the main menu finds an option of ProxMenux, an OCI application or a Helper-Script by its name or by related words, and opens it where it lives: the scripts it launches are the ones the menus launch.""" import importlib.util import json from pathlib import Path import re import runpy import unittest ROOT = Path(__file__).resolve().parents[3] SCRIPTS = ROOT / "scripts" def load(): spec = importlib.util.spec_from_file_location("search_menu", SCRIPTS / "menus/search_menu.py") module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) # The repository in the place of the installed copy. module.BASE, module.SCRIPTS = ROOT, SCRIPTS module.OCI_INDEX = ROOT / "oci/catalog/index.json" module.HELPERS_CACHE = ROOT / "json/helpers_cache.json" module._translations = {} return module class IndexTests(unittest.TestCase): @classmethod def setUpClass(cls): cls.index = json.loads((SCRIPTS / "menus/search_index.json").read_text(encoding="utf-8")) cls.spanish = json.loads((ROOT / "lang/es.json").read_text(encoding="utf-8")) def test_every_entry_opens_a_script_that_exists(self): missing = sorted({item["script"] for item in self.index if not (SCRIPTS / item["script"]).is_file()}) self.assertEqual(missing, []) def test_every_title_is_a_text_the_menus_already_translate(self): names = {"ZimaOS", "Synology DSM"} unknown = [item["title"] for item in self.index if item["title"] not in self.spanish and item["title"] not in names] self.assertEqual(unknown, []) self.assertEqual([item["menu"] for item in self.index if item["menu"] not in self.spanish], []) def test_every_script_a_menu_launches_can_be_found(self): indexed = {item["script"] for item in self.index} launched = set() for menu in sorted((SCRIPTS / "menus").glob("*.sh")): if menu.name in ("main_menu.sh", "lxc_menu.sh"): continue launched |= set(re.findall(r'bash "\$LOCAL_SCRIPTS/([A-Za-z0-9_./-]+\.sh)"', menu.read_text())) launched -= {"menus/main_menu.sh"} # Opened from their own menu, which is what the index points at. launched -= {"post_install/auto_post_install.sh", "utilities/proxmox_update.sh", "utilities/upgrade_pve8_to_pve9.sh"} self.assertEqual(sorted(launched - indexed), []) def test_the_main_menu_offers_the_search_and_opens_what_it_hands_back(self): menu = (SCRIPTS / "menus/main_menu.sh").read_text() self.assertIn('search "$(translate "Search options and applications")"', menu) self.assertIn('search_menu.py" --handoff "$handoff"', menu) self.assertIn('[[ "${target[0]:-}" == "$LOCAL_SCRIPTS"/* && -f "${target[0]}" ]]', menu) self.assertIn('exec bash "${target[@]}"', menu) def test_an_option_inside_a_menu_names_one_that_menu_has(self): for item in self.index: argument = item.get("argument") if not argument: continue script = (SCRIPTS / item["script"]).read_text() self.assertIn("PRESELECTED_OPTION", script, item["script"]) if not argument.isdigit(): self.assertIn(argument, script, f"{item['script']}: {argument}") class CatalogTests(unittest.TestCase): @classmethod def setUpClass(cls): cls.search = load() cls.items = cls.search.catalog(refresh=False) def found(self, query): return self.search.search(self.items, query) def test_the_three_sources_are_in_the_catalog(self): self.assertEqual({item["source"] for item in self.items}, set(self.search.SOURCES)) def test_proxmenux_comes_first_then_oci_then_helper_scripts(self): sources = [item["source"] for item in self.found("samba")] self.assertEqual(sources, sorted(sources, key=self.search.SOURCES.index)) self.assertEqual(sources[0], "ProxMenux") def test_a_name_is_found_by_the_start_of_any_of_its_words(self): self.assertIn("Jellyfin", [item["title"] for item in self.found("jelly")]) self.assertTrue(any(item["source"] == "OCI Manager" for item in self.found("plex"))) def test_accents_and_case_do_not_matter(self): self.assertEqual([item["title"] for item in self.found("NVIDIA")], [item["title"] for item in self.found("nvidia")]) def test_related_words_find_an_option(self): self.assertTrue(any("NFS" in item["title"] for item in self.found("nfs storage"))) self.assertTrue(any(item["action"][-1].endswith("fail2ban_installer.sh") for item in self.found("fail2ban"))) def test_a_match_by_category_comes_after_the_names(self): matches = self.found("vpn") self.assertTrue(any(item["title"] == "Tailscale" for item in matches)) by_category = False for item in matches: words = re.findall(r"[a-z0-9]+", self.search.fold(item["terms"])) in_name = any(word.startswith("vpn") for word in words) self.assertFalse(in_name and by_category) by_category = by_category or not in_name def test_an_application_is_not_found_by_what_its_description_mentions(self): titles = [item["title"] for item in self.found("plex")] self.assertNotIn("Jellyfin", titles) self.assertTrue(all("plex" in title.casefold() for title in titles)) def test_nothing_matches_nothing(self): self.assertEqual(self.found("zzqqxx"), []) self.assertEqual(self.found(" "), []) def test_a_sub_menu_is_handed_back_to_the_main_menu(self): by_script = {item["action"][1]: item for item in self.items if item["source"] == "ProxMenux"} self.assertTrue(by_script[str(SCRIPTS / "menus/network_menu.sh")]["handoff"]) self.assertFalse(by_script[str(SCRIPTS / "storage/format-disk.sh")]["handoff"]) def test_an_option_inside_a_menu_is_given_to_that_menu(self): zfs = next(item for item in self.items if item["action"][1:] == [str(SCRIPTS / "help_info_menu.sh"), "7"]) self.assertFalse(zfs["handoff"]) language = next(item for item in self.items if item["action"][-1] == "change_language") self.assertEqual(language["action"][1], str(SCRIPTS / "menus/config_menu.sh")) self.assertTrue(language["handoff"]) class OpenedInPlaceTests(unittest.TestCase): def test_an_option_of_the_post_install_comes_selected(self): script = (SCRIPTS / "post_install/customizable_post_install.sh").read_text() self.assertIn('PRESELECTED_OPTION="${1:-}"', script) self.assertIn('--default-item "${preselected_item:-1}"', script) def test_a_utility_comes_selected(self): script = (SCRIPTS / "utilities/system_utils.sh").read_text() self.assertIn('PRESELECTED_UTILITY="${1:-}"', script) def test_a_helper_script_is_opened_on_its_own(self): script = (SCRIPTS / "menus/menu_Helper_Scripts.sh").read_text() self.assertIn('run_script_by_slug "$1"', script) def test_an_oci_application_opens_its_page(self): cli = (ROOT / "oci/src/proxmenux_oci/cli.py").read_text() self.assertIn('subparsers.add_parser("open"', cli) class TranslationTests(unittest.TestCase): """What the search and the main menu say reaches the translation workflow, read with the folders the workflow itself passes.""" @classmethod def setUpClass(cls): workflow = (ROOT / ".github/workflows/build-translation-cache.yml").read_text() extractor = runpy.run_path(str(ROOT / ".github/scripts/build_translation_cache.py")) folders = [ROOT / folder for folder in re.findall(r"--python-dir (\S+)", workflow)] cls.found = set(extractor["extract_python_texts"](folders)) cls.found |= set(extractor["extract_translate_texts"](SCRIPTS)) cls.triggers = workflow def test_every_text_of_the_search_is_found(self): source = (SCRIPTS / "menus/search_menu.py").read_text() said = set(re.findall(r"translate\('([^']+)'\)", source)) self.assertIn("No results", said) self.assertEqual(sorted(said - self.found), []) def test_the_title_of_the_main_menu_is_found(self): self.assertIn("Main menu", self.found) def test_a_change_in_the_search_runs_the_workflow(self): self.assertIn("'scripts/**/*.py'", self.triggers) if __name__ == "__main__": unittest.main()