mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-11-01 18:32:13 +00:00
210 lines
9.9 KiB
Python
210 lines
9.9 KiB
Python
"""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
|
|
import os
|
|
from pathlib import Path
|
|
import re
|
|
import runpy
|
|
import shlex
|
|
import subprocess
|
|
import tempfile
|
|
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_pve_menu_launches_can_be_found(self):
|
|
indexed = {item["script"] for item in self.index}
|
|
launched = set()
|
|
for menu in sorted((SCRIPTS / "menus").glob("*.sh")):
|
|
# PBS replaces the PVE main menu and does not use its search.
|
|
# The exclusive platform dispatch is executed in the test below.
|
|
if menu.name in ("main_menu.sh", "lxc_menu.sh", "pbs_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_pbs_replaces_the_searchable_pve_menu(self):
|
|
menu = (SCRIPTS / "menus/main_menu.sh").read_text()
|
|
dispatch = menu[menu.rindex('source "$LOCAL_SCRIPTS/global/platform-functions.sh"'):]
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
scripts = Path(directory)
|
|
(scripts / "global").mkdir()
|
|
(scripts / "menus").mkdir()
|
|
helper = scripts / "global/platform-functions.sh"
|
|
helper.write_text(
|
|
"source " + shlex.quote(str(SCRIPTS / "global/platform-functions.sh")) + "\n"
|
|
'pmx_platform_field() { printf "%s" "$TEST_PROXMENUX_PRODUCT"; }\n')
|
|
(scripts / "menus/pbs_menu.sh").write_text('printf "PBS menu\\n"\n')
|
|
harness = 'show_menu() { printf "PVE search menu\\n"; }\n' + dispatch
|
|
for product, expected in (("pve", "PVE search menu"), ("pbs", "PBS menu")):
|
|
with self.subTest(product=product):
|
|
result = subprocess.run(["bash", "-e", "-c", harness], text=True, capture_output=True,
|
|
env={**os.environ, "LOCAL_SCRIPTS": str(scripts),
|
|
"TEST_PROXMENUX_PRODUCT": product})
|
|
self.assertEqual(result.returncode, 0, result.stderr)
|
|
self.assertEqual(result.stdout.strip(), expected)
|
|
|
|
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()
|