The fork takes its own name everywhere a user can see it: binaries (voculinux, voculinux-gui), desktop entry, autostart, tray, D-Bus namespace (com.voculinux.Voculinux, no alias for the old name), config/data/cache dirs, single-instance lock, IBus engine identity, tray icons, resource prefixes, VOCULINUX_* environment names, and the update-checker user agent. The internal Python module stays vocalinux and the distribution metadata keeps the upstream URLs as provenance. On first run a previous Vocalinux install's config.json, custom dictionary, and portal restore token are copied once into the new locations (new config always wins, no merge, no write-back); models re-resolve through the pinned-checksum download path. An offline naming-sweep test proves no old-name strings remain on user-visible surfaces outside the allowlist. Refs #18
129 lines
5.7 KiB
Python
129 lines
5.7 KiB
Python
"""Regression tests for issue #478.
|
|
|
|
On Wayland, IBus only delivers commit_text() to applications through a *real*
|
|
IM engine. A bare ``xkb:*`` engine (or none) is a layout passthrough, so
|
|
selecting the IBus backend there is a silent no-op. is_ibus_active_input_method()
|
|
must require a real engine on Wayland regardless of how IBus was detected, while
|
|
leaving X11/XWayland (XIM) behavior unchanged.
|
|
|
|
Note: we patch via ``patch.object`` on a held module reference (and call the
|
|
function through that same reference) rather than by dotted string, so the
|
|
patched ``get_current_engine`` / ``is_ibus_daemon_running`` and the function
|
|
under test always share one module object even when other test files re-import
|
|
``ibus_engine`` during a full-suite run.
|
|
"""
|
|
|
|
import sys
|
|
import unittest
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
# Mock GI so importing ibus_engine does not require a real IBus/GTK stack.
|
|
_mock_gi = MagicMock()
|
|
_mock_gi_repo = MagicMock()
|
|
_mock_gi_repo.IBus = MagicMock()
|
|
_mock_gi_repo.GLib = MagicMock()
|
|
_mock_gi_repo.GObject = MagicMock()
|
|
_mock_gi_repo.IBus.Engine = MagicMock
|
|
_mock_gi_repo.GLib.MainLoop = MagicMock
|
|
sys.modules["gi"] = _mock_gi
|
|
sys.modules["gi.repository"] = _mock_gi_repo
|
|
|
|
for _key in list(sys.modules.keys()):
|
|
if "voculinux" in _key and "ibus_engine" in _key:
|
|
del sys.modules[_key]
|
|
|
|
import vocalinux.text_injection.ibus_engine as ibus_engine # noqa: E402
|
|
|
|
|
|
class TestIsRealIBusEngine(unittest.TestCase):
|
|
def test_real_engines(self):
|
|
for engine in ("anthy", "libpinyin", "hangul", "mozc-jp"):
|
|
self.assertTrue(ibus_engine._is_real_ibus_engine(engine), engine)
|
|
|
|
def test_layout_only_or_missing_engines(self):
|
|
for engine in ("xkb:us::eng", "xkb:de::ger", "xkb:gb::eng", "", None, "No global engine"):
|
|
self.assertFalse(ibus_engine._is_real_ibus_engine(engine), repr(engine))
|
|
|
|
|
|
class TestWaylandRequiresRealEngine(unittest.TestCase):
|
|
@patch.object(ibus_engine, "get_current_engine", return_value="xkb:us::eng")
|
|
@patch.object(ibus_engine, "is_ibus_daemon_running", return_value=True)
|
|
@patch.dict("os.environ", {"XDG_SESSION_TYPE": "wayland", "QT_IM_MODULE": "ibus"}, clear=True)
|
|
def test_bare_xkb_engine_inactive_even_with_env_var(self, *_):
|
|
# GNOME/Mutter: QT_IM_MODULE=ibus but only a bare xkb engine -> no-op.
|
|
self.assertFalse(ibus_engine.is_ibus_active_input_method())
|
|
|
|
@patch.object(ibus_engine, "get_current_engine", return_value="anthy")
|
|
@patch.object(ibus_engine, "is_ibus_daemon_running", return_value=True)
|
|
@patch.dict("os.environ", {"XDG_SESSION_TYPE": "wayland"}, clear=True)
|
|
def test_real_engine_is_active(self, *_):
|
|
self.assertTrue(ibus_engine.is_ibus_active_input_method())
|
|
|
|
@patch.object(ibus_engine, "get_current_engine", return_value=None)
|
|
@patch.object(ibus_engine, "is_ibus_daemon_running", return_value=True)
|
|
@patch.dict("os.environ", {"XDG_SESSION_TYPE": "wayland", "GTK_IM_MODULE": "ibus"}, clear=True)
|
|
def test_no_engine_is_inactive(self, *_):
|
|
self.assertFalse(ibus_engine.is_ibus_active_input_method())
|
|
|
|
|
|
class TestX11BehaviorUnchanged(unittest.TestCase):
|
|
@patch.object(ibus_engine, "get_current_engine", return_value="xkb:us::eng")
|
|
@patch.object(ibus_engine, "is_ibus_daemon_running", return_value=True)
|
|
@patch.dict("os.environ", {"XDG_SESSION_TYPE": "x11"}, clear=True)
|
|
def test_daemon_with_xkb_engine_still_active_on_x11(self, *_):
|
|
# XIM delivers even with a bare xkb engine, so the daemon fallback stands.
|
|
self.assertTrue(ibus_engine.is_ibus_active_input_method())
|
|
|
|
@patch.object(ibus_engine, "get_current_engine", return_value=None)
|
|
@patch.object(ibus_engine, "is_ibus_daemon_running", return_value=False)
|
|
@patch.dict("os.environ", {"XDG_SESSION_TYPE": "x11", "GTK_IM_MODULE": "ibus"}, clear=True)
|
|
def test_env_var_is_active_on_x11(self, *_):
|
|
self.assertTrue(ibus_engine.is_ibus_active_input_method())
|
|
|
|
@patch.object(ibus_engine, "get_current_engine", return_value=None)
|
|
@patch.object(ibus_engine, "is_ibus_daemon_running", return_value=False)
|
|
@patch.dict("os.environ", {"XDG_SESSION_TYPE": "x11", "GTK_IM_MODULE": "fcitx"}, clear=True)
|
|
def test_other_im_configured_is_inactive(self, *_):
|
|
self.assertFalse(ibus_engine.is_ibus_active_input_method())
|
|
|
|
|
|
class TestKdeDoesNotTreatLeftoverDaemonAsIm(unittest.TestCase):
|
|
@patch.object(ibus_engine, "get_current_engine", return_value="xkb:us::eng")
|
|
@patch.object(ibus_engine, "is_ibus_daemon_running", return_value=True)
|
|
@patch.dict(
|
|
"os.environ",
|
|
{"XDG_SESSION_TYPE": "x11", "XDG_CURRENT_DESKTOP": "KDE"},
|
|
clear=True,
|
|
)
|
|
def test_kde_x11_daemon_without_im_env_is_inactive(self, *_):
|
|
# CachyOS/KDE: we started (or found) ibus-daemon, but Qt/GTK never use it (#752).
|
|
self.assertFalse(ibus_engine.is_ibus_active_input_method())
|
|
|
|
@patch.object(ibus_engine, "get_current_engine", return_value="xkb:us::eng")
|
|
@patch.object(ibus_engine, "is_ibus_daemon_running", return_value=True)
|
|
@patch.dict(
|
|
"os.environ",
|
|
{
|
|
"XDG_SESSION_TYPE": "x11",
|
|
"XDG_CURRENT_DESKTOP": "KDE",
|
|
"GTK_IM_MODULE": "ibus",
|
|
},
|
|
clear=True,
|
|
)
|
|
def test_kde_x11_with_ibus_env_still_active(self, *_):
|
|
self.assertTrue(ibus_engine.is_ibus_active_input_method())
|
|
|
|
@patch.object(ibus_engine, "get_current_engine", return_value="xkb:us::eng")
|
|
@patch.object(ibus_engine, "is_ibus_daemon_running", return_value=True)
|
|
@patch.dict(
|
|
"os.environ",
|
|
{"XDG_SESSION_TYPE": "x11", "KDE_FULL_SESSION": "true"},
|
|
clear=True,
|
|
)
|
|
def test_kde_full_session_without_im_env_is_inactive(self, *_):
|
|
self.assertFalse(ibus_engine.is_ibus_active_input_method())
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|