// Fenrir console screen reader. // Copyright (c) 2026 Storm Dragon // SPDX-License-Identifier: GPL-3.0-or-later // // This program is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the Free // Software Foundation, either version 3 of the License, or (at your option) // any later version. // // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for // more details. // // You should have received a copy of the GNU General Public License along with // this program. If not, see . package scripts import ( "os" "path/filepath" "reflect" "testing" "git.stormux.org/storm/fenrir/internal/input" ) func TestPythonFilenameGrammar(t *testing.T) { for _, fixture := range []struct { name string keys []string }{ {"musicplayer__-__KEY_SHIFT__+__KEY_U.sh", []string{"KEY_SHIFT", "KEY_U", "KEY_SCRIPT"}}, {"KEY_A", []string{"KEY_A", "KEY_SCRIPT"}}, {"Name with spaces__-__key_ctrl__+__key_f12.py", []string{"KEY_CTRL", "KEY_F12", "KEY_SCRIPT"}}, {"explicit__-__KEY_SCRIPT__+__KEY_KPPLUS", []string{"KEY_SCRIPT", "KEY_KPPLUS"}}, {"keys__-__KEY_A__+__KEY_B", []string{"KEY_A", "KEY_B", "KEY_SCRIPT"}}, {"media__-__KEY_PLAYPAUSE", []string{"KEY_PLAYPAUSE", "KEY_SCRIPT"}}, } { script, ok := Parse_filename(fixture.name) if !ok || !reflect.DeepEqual(script.Keys, fixture.keys) { t.Fatal(fixture.name, script, ok) } } for _, name := range []string{"__hidden__-__KEY_A.sh", ".hidden__-__KEY_A", "bad__-__KEY_A__-__KEY_B", "bad__-__KEY_NO_SUCH_KEY", "bad__-__KEY_A__+__", "unbound.sh"} { if _, ok := Parse_filename(name); ok { t.Fatal("accepted invalid filename", name) } } } func TestPythonDiscoveryPrecedenceVariantsAndConflicts(t *testing.T) { root := t.TempDir() local, system := filepath.Join(root, "local"), filepath.Join(root, "system") for _, directory := range []string{local, system} { if err := os.Mkdir(directory, 0700); err != nil { t.Fatal(err) } } write := func(directory, name string) { t.Helper() if err := os.WriteFile(filepath.Join(directory, name), []byte("#!/bin/sh\n"), 0600); err != nil { t.Fatal(err) } } write(local, "same__-__KEY_A.sh") write(local, "music__-__KEY_SHIFT__+__KEY_U.sh") write(local, "music__-__KEY_SHIFT__+__KEY_X.sh") write(system, "same__-__KEY_B.sh") write(system, "other__-__KEY_C.sh") write(system, "conflict__-__KEY_D.sh") write(system, "occupied__-__KEY_C.sh") if err := os.Symlink(filepath.Join(local, "same__-__KEY_A.sh"), filepath.Join(local, "link__-__KEY_E.sh")); err != nil { t.Fatal(err) } if err := os.Mkdir(filepath.Join(local, "directory__-__KEY_F.sh"), 0700); err != nil { t.Fatal(err) } result, problems := Discover([]string{filepath.Join(root, "missing"), local, system}, map[string]bool{input.Script_chord([]string{"KEY_D", "KEY_SCRIPT"}): true}) if len(problems) != 0 { t.Fatal(problems) } var names []string for _, script := range result { names = append(names, filepath.Base(script.Path)) } want := []string{"link__-__KEY_E.sh", "music__-__KEY_SHIFT__+__KEY_U.sh", "music__-__KEY_SHIFT__+__KEY_X.sh", "same__-__KEY_A.sh", "occupied__-__KEY_C.sh"} if !reflect.DeepEqual(names, want) { t.Fatal(names, want) } } func TestPathsKeepPythonResourceRootAndDeduplicate(t *testing.T) { home := t.TempDir() got := Paths(home, "~/.local/stormux/fenrir", "") want := []string{filepath.Join(home, ".local/stormux/fenrir")} if !reflect.DeepEqual(got, want) { t.Fatal(got, want) } if got := Paths(home, SystemPath, "/bundle/config/scripts"); len(got) != 3 || got[1] != SystemPath { t.Fatal(got) } }