Ajoute la configuration des associations application/preset, le service de suivi du focus, l'intégration GUI et les fichiers d'installation nécessaires. Ajoute les tests unitaires ciblés des bindings, du service de focus, des migrations et des composants GUI associés. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
182 lines
6.9 KiB
Python
182 lines
6.9 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
# input-remapper - GUI for device specific keyboard mappings
|
|
# Copyright (C) 2025 sezanzeb <b8x45ygc9@mozmail.com>
|
|
#
|
|
# This file is part of input-remapper.
|
|
#
|
|
# input-remapper 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.
|
|
#
|
|
# input-remapper 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 input-remapper. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
|
|
import json
|
|
import os
|
|
import unittest
|
|
|
|
from inputremapper.configs.global_config import GlobalConfig
|
|
from inputremapper.logging.logger import VERSION
|
|
from tests.lib.test_setup import test_setup
|
|
|
|
|
|
@test_setup
|
|
class TestGlobalConfig(unittest.TestCase):
|
|
def test_autoload(self):
|
|
global_config = GlobalConfig()
|
|
self.assertEqual(len(global_config.iterate_autoload_presets()), 0)
|
|
self.assertFalse(global_config.is_autoloaded("d1", "a"))
|
|
self.assertFalse(global_config.is_autoloaded("d2", "b"))
|
|
self.assertEqual(global_config.get_autoload_preset("d1"), None)
|
|
self.assertEqual(global_config.get_autoload_preset("d2"), None)
|
|
|
|
global_config.set_autoload_preset("d1", "a")
|
|
self.assertEqual(len(global_config.iterate_autoload_presets()), 1)
|
|
self.assertTrue(global_config.is_autoloaded("d1", "a"))
|
|
self.assertFalse(global_config.is_autoloaded("d2", "b"))
|
|
|
|
global_config.set_autoload_preset("d2", "b")
|
|
self.assertEqual(len(global_config.iterate_autoload_presets()), 2)
|
|
self.assertTrue(global_config.is_autoloaded("d1", "a"))
|
|
self.assertTrue(global_config.is_autoloaded("d2", "b"))
|
|
self.assertEqual(global_config.get_autoload_preset("d1"), "a")
|
|
self.assertEqual(global_config.get_autoload_preset("d2"), "b")
|
|
|
|
global_config.set_autoload_preset("d2", "c")
|
|
self.assertEqual(len(global_config.iterate_autoload_presets()), 2)
|
|
self.assertTrue(global_config.is_autoloaded("d1", "a"))
|
|
self.assertFalse(global_config.is_autoloaded("d2", "b"))
|
|
self.assertTrue(global_config.is_autoloaded("d2", "c"))
|
|
self.assertEqual(global_config._config["autoload"]["d2"], "c")
|
|
self.assertListEqual(
|
|
list(global_config.iterate_autoload_presets()),
|
|
[("d1", "a"), ("d2", "c")],
|
|
)
|
|
|
|
global_config.set_autoload_preset("d2", None)
|
|
self.assertTrue(global_config.is_autoloaded("d1", "a"))
|
|
self.assertFalse(global_config.is_autoloaded("d2", "b"))
|
|
self.assertFalse(global_config.is_autoloaded("d2", "c"))
|
|
self.assertListEqual(
|
|
list(global_config.iterate_autoload_presets()),
|
|
[("d1", "a")],
|
|
)
|
|
self.assertEqual(global_config.get_autoload_preset("d1"), "a")
|
|
|
|
self.assertRaises(ValueError, global_config.is_autoloaded, "d1", None)
|
|
self.assertRaises(ValueError, global_config.is_autoloaded, None, "a")
|
|
|
|
def test_initial(self):
|
|
global_config = GlobalConfig()
|
|
# when loading for the first time, create a config file with
|
|
# the default values
|
|
self.assertFalse(os.path.exists(global_config.path))
|
|
global_config.load_config()
|
|
self.assertTrue(os.path.exists(global_config.path))
|
|
|
|
with open(global_config.path, "r") as file:
|
|
config = json.load(file)
|
|
self.assertEqual(
|
|
config,
|
|
{
|
|
"version": VERSION,
|
|
"autoload": {},
|
|
"app_binding_enabled": False,
|
|
"app_bindings": [],
|
|
},
|
|
)
|
|
|
|
def test_save_load(self):
|
|
global_config = GlobalConfig()
|
|
self.assertEqual(len(global_config.iterate_autoload_presets()), 0)
|
|
|
|
global_config.load_config()
|
|
self.assertEqual(len(global_config.iterate_autoload_presets()), 0)
|
|
|
|
global_config.set_autoload_preset("d1", "a")
|
|
global_config.set_autoload_preset("d2", "b")
|
|
|
|
global_config.load_config()
|
|
|
|
self.assertListEqual(
|
|
list(global_config.iterate_autoload_presets()),
|
|
[("d1", "a"), ("d2", "b")],
|
|
)
|
|
|
|
# -- app bindings ------------------------------------------------------
|
|
|
|
def test_app_binding_enabled_default_false(self):
|
|
global_config = GlobalConfig()
|
|
self.assertFalse(global_config.get_app_binding_enabled())
|
|
|
|
def test_set_app_binding_enabled_roundtrip(self):
|
|
global_config = GlobalConfig()
|
|
global_config.set_app_binding_enabled(True)
|
|
self.assertTrue(global_config.get_app_binding_enabled())
|
|
|
|
# persisted and reloadable
|
|
reloaded = GlobalConfig()
|
|
reloaded.load_config()
|
|
self.assertTrue(reloaded.get_app_binding_enabled())
|
|
|
|
global_config.set_app_binding_enabled(False)
|
|
self.assertFalse(global_config.get_app_binding_enabled())
|
|
|
|
def test_app_bindings_default_empty(self):
|
|
global_config = GlobalConfig()
|
|
self.assertEqual(global_config.get_app_bindings(), [])
|
|
|
|
def test_set_app_bindings_roundtrip(self):
|
|
from inputremapper.configs.app_binding import (
|
|
AppBinding,
|
|
BoundPreset,
|
|
MatchType,
|
|
)
|
|
|
|
bindings = [
|
|
AppBinding(
|
|
app_id="firefox",
|
|
match=MatchType.wm_class,
|
|
presets=[BoundPreset(group_key="Foo Device", preset="preset1")],
|
|
),
|
|
AppBinding(app_id="term.*", match=MatchType.title_regex),
|
|
]
|
|
global_config = GlobalConfig()
|
|
global_config.set_app_bindings(bindings)
|
|
|
|
# serialized as plain dicts in config.json
|
|
with open(global_config.path, "r") as file:
|
|
raw = json.load(file)
|
|
self.assertEqual(len(raw["app_bindings"]), 2)
|
|
self.assertEqual(raw["app_bindings"][0]["app_id"], "firefox")
|
|
|
|
# reloaded into model objects
|
|
reloaded = GlobalConfig()
|
|
reloaded.load_config()
|
|
result = reloaded.get_app_bindings()
|
|
self.assertEqual(result, bindings)
|
|
|
|
def test_get_app_bindings_skips_invalid(self):
|
|
global_config = GlobalConfig()
|
|
global_config.load_config()
|
|
# inject an invalid binding (empty app_id) directly into the raw config
|
|
global_config._config["app_bindings"] = [
|
|
{"app_id": "valid", "match": "wm_class", "presets": []},
|
|
{"app_id": "", "match": "wm_class", "presets": []},
|
|
]
|
|
result = global_config.get_app_bindings()
|
|
self.assertEqual(len(result), 1)
|
|
self.assertEqual(result[0].app_id, "valid")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|