mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-07 01:15:33 +00:00
This change rename the test files for Linux according to the discussion at the Keyman conference in November 2024. Python is pretty opinionated about the naming of files, so we have to use `*_tests.py` as test filename instead of the usual `*.tests.py`.
381 lines
16 KiB
Python
381 lines
16 KiB
Python
#!/usr/bin/python3
|
|
import os
|
|
import tempfile
|
|
import unittest
|
|
from unittest.mock import patch, ANY
|
|
from keyman_config import __version__
|
|
from keyman_config.get_kmp import InstallLocation
|
|
from keyman_config.install_kmp import InstallError, InstallKmp
|
|
|
|
|
|
class InstallKmpBase(unittest.TestCase):
|
|
|
|
def setUp(self):
|
|
patcher1 = patch('keyman_config.install_kmp.install_to_ibus')
|
|
self.mockInstallToIbus = patcher1.start()
|
|
self.addCleanup(patcher1.stop)
|
|
patcher2 = patch('keyman_config.install_kmp.restart_ibus')
|
|
self.mockRestartIbus = patcher2.start()
|
|
self.addCleanup(patcher2.stop)
|
|
patcher3 = patch('keyman_config.install_kmp.get_ibus_bus')
|
|
self.mockGetIbusBus = patcher3.start()
|
|
self.addCleanup(patcher3.stop)
|
|
patcher4 = patch('keyman_config.install_kmp.GnomeKeyboardsUtil')
|
|
self.mockGnomeKeyboardsUtilClass = patcher4.start()
|
|
self.addCleanup(patcher4.stop)
|
|
patcher5 = patch('keyman_config.install_kmp.get_keyboard_dir')
|
|
self.mockGetKeyboardDir = patcher5.start()
|
|
self.addCleanup(patcher5.stop)
|
|
patcher6 = patch('keyman_config.install_kmp.extract_kmp')
|
|
self.mockExtractKmp = patcher6.start()
|
|
self.addCleanup(patcher6.stop)
|
|
patcher7 = patch('keyman_config.install_kmp.extractico')
|
|
self.mockExtractIco = patcher7.start()
|
|
self.addCleanup(patcher7.stop)
|
|
patcher8 = patch('keyman_config.install_kmp.is_gnome_desktop')
|
|
self.mockIsGnomeShell = patcher8.start()
|
|
self.addCleanup(patcher8.stop)
|
|
self.mockIsGnomeShell.return_value = False
|
|
patcher9 = patch('keyman_config.install_kmp.is_fcitx_running')
|
|
self.mockIsFcitxRunning = patcher9.start()
|
|
self.addCleanup(patcher9.stop)
|
|
self.mockIsFcitxRunning.return_value = False
|
|
patcher10 = patch('keyman_config.install_kmp.CustomKeyboards')
|
|
self.mockCustomKeyboardsClass = patcher10.start()
|
|
self.addCleanup(patcher10.stop)
|
|
|
|
|
|
class InstallKeyboardsToIbusTests(InstallKmpBase):
|
|
def test_InstallKeyboardsToIbus_NoIbus(self):
|
|
# Setup
|
|
self.mockGetIbusBus.return_value = None
|
|
# Execute
|
|
InstallKmp()._install_keyboards_to_ibus([], None)
|
|
# Verify
|
|
self.mockRestartIbus.assert_not_called()
|
|
|
|
def test_InstallKeyboardsToIbus_SingleKbNoLanguages(self):
|
|
# Setup
|
|
bus = self.mockGetIbusBus.return_value
|
|
keyboards = [{'id': 'foo1'}]
|
|
# Execute
|
|
InstallKmp()._install_keyboards_to_ibus(keyboards, 'fooDir')
|
|
# Verify
|
|
self.mockInstallToIbus.assert_called_once_with(ANY, 'fooDir/foo1.kmx')
|
|
self.mockRestartIbus.assert_called_once()
|
|
bus.destroy.assert_called_once()
|
|
|
|
def test_InstallKeyboardsToIbus_MultipleKbsNoLanguages(self):
|
|
# Setup
|
|
bus = self.mockGetIbusBus.return_value
|
|
keyboards = [{'id': 'foo1'}, {'id': 'foo2'}]
|
|
# Execute
|
|
InstallKmp()._install_keyboards_to_ibus(keyboards, 'fooDir')
|
|
# Verify
|
|
self.mockInstallToIbus.assert_any_call(ANY, 'fooDir/foo1.kmx')
|
|
self.mockInstallToIbus.assert_any_call(ANY, 'fooDir/foo2.kmx')
|
|
self.mockRestartIbus.assert_called_once()
|
|
bus.destroy.assert_called_once()
|
|
|
|
def test_InstallKeyboardsToIbus_SingleKbSingleLanguage(self):
|
|
# Setup
|
|
bus = self.mockGetIbusBus.return_value
|
|
keyboards = [{'id': 'foo1', 'languages': [{'id': 'en'}]}]
|
|
# Execute
|
|
InstallKmp()._install_keyboards_to_ibus(keyboards, 'fooDir')
|
|
# Verify
|
|
self.mockInstallToIbus.assert_called_once_with(ANY, 'en:fooDir/foo1.kmx')
|
|
self.mockRestartIbus.assert_called_once()
|
|
bus.destroy.assert_called_once()
|
|
|
|
def test_InstallKeyboardsToIbus_SingleKbMultipleLanguages(self):
|
|
# Setup
|
|
bus = self.mockGetIbusBus.return_value
|
|
keyboards = [{'id': 'foo1', 'languages': [{'id': 'en'}, {'id': 'fr'}]}]
|
|
# Execute
|
|
InstallKmp()._install_keyboards_to_ibus(keyboards, 'fooDir')
|
|
# Verify
|
|
self.mockInstallToIbus.assert_called_once()
|
|
self.mockInstallToIbus.assert_called_with(ANY, 'en:fooDir/foo1.kmx')
|
|
# self.mockInstallToIbus.assert_not_called_with(ANY, 'fr:fooDir/foo1.kmx')
|
|
self.mockRestartIbus.assert_called_once()
|
|
bus.destroy.assert_called_once()
|
|
|
|
def test_InstallKeyboardsToIbus_SingleKbMultipleLanguages_GivenLanguage(self):
|
|
# Setup
|
|
bus = self.mockGetIbusBus.return_value
|
|
keyboards = [{'id': 'foo1', 'languages': [{'id': 'en'}, {'id': 'fr'}]}]
|
|
# Execute
|
|
InstallKmp()._install_keyboards_to_ibus(keyboards, 'fooDir', 'fr')
|
|
# Verify
|
|
self.mockInstallToIbus.assert_called_once()
|
|
self.mockInstallToIbus.assert_called_with(ANY, 'fr:fooDir/foo1.kmx')
|
|
# self.mockInstallToIbus.assert_not_called_with(ANY, 'en:fooDir/foo1.kmx')
|
|
self.mockRestartIbus.assert_called_once()
|
|
bus.destroy.assert_called_once()
|
|
|
|
def test_InstallKeyboardsToIbus_SingleKbMultipleLanguages_OtherLanguage(self):
|
|
# Setup
|
|
bus = self.mockGetIbusBus.return_value
|
|
keyboards = [{'id': 'foo1', 'languages': [{'id': 'en'}, {'id': 'fr'}]}]
|
|
# Execute
|
|
InstallKmp()._install_keyboards_to_ibus(keyboards, 'fooDir', 'de')
|
|
# Verify
|
|
self.mockInstallToIbus.assert_called_once()
|
|
self.mockInstallToIbus.assert_called_with(ANY, 'de:fooDir/foo1.kmx')
|
|
# self.mockInstallToIbus.assert_not_called_with(ANY, 'en:fooDir/foo1.kmx')
|
|
self.mockRestartIbus.assert_called_once()
|
|
bus.destroy.assert_called_once()
|
|
|
|
|
|
class InstallKeyboardsToGnomeTests(InstallKmpBase):
|
|
def test_InstallKeyboardsToGnome_SingleKbNoLanguages(self):
|
|
# Setup
|
|
mockGnomeKeyboardsUtilInstance = self.mockGnomeKeyboardsUtilClass.return_value
|
|
mockGnomeKeyboardsUtilInstance.read_input_sources.return_value = [('xkb', 'en')]
|
|
keyboards = [{'id': 'foo1'}]
|
|
# Execute
|
|
InstallKmp()._install_keyboards_to_gnome(keyboards, 'fooDir')
|
|
# Verify
|
|
mockGnomeKeyboardsUtilInstance.write_input_sources.assert_called_once_with(
|
|
[('xkb', 'en'), ('ibus', 'fooDir/foo1.kmx')])
|
|
self.mockRestartIbus.assert_not_called()
|
|
|
|
def test_InstallKeyboardsToGnome_MultipleKbsNoLanguages(self):
|
|
# Setup
|
|
mockGnomeKeyboardsUtilInstance = self.mockGnomeKeyboardsUtilClass.return_value
|
|
mockGnomeKeyboardsUtilInstance.read_input_sources.return_value = [('xkb', 'en')]
|
|
keyboards = [{'id': 'foo1'}, {'id': 'foo2'}]
|
|
# Execute
|
|
InstallKmp()._install_keyboards_to_gnome(keyboards, 'fooDir')
|
|
# Verify
|
|
mockGnomeKeyboardsUtilInstance.write_input_sources.assert_called_once_with(
|
|
[('xkb', 'en'), ('ibus', 'fooDir/foo1.kmx'), ('ibus', 'fooDir/foo2.kmx')])
|
|
self.mockRestartIbus.assert_not_called()
|
|
|
|
def test_InstallKeyboardsToGnome_SingleKbSingleLanguage(self):
|
|
# Setup
|
|
mockGnomeKeyboardsUtilInstance = self.mockGnomeKeyboardsUtilClass.return_value
|
|
mockGnomeKeyboardsUtilInstance.read_input_sources.return_value = [('xkb', 'en')]
|
|
keyboards = [{'id': 'foo1', 'languages': [{'id': 'en'}]}]
|
|
# Execute
|
|
InstallKmp()._install_keyboards_to_gnome(keyboards, 'fooDir')
|
|
# Verify
|
|
mockGnomeKeyboardsUtilInstance.write_input_sources.assert_called_once_with(
|
|
[('xkb', 'en'), ('ibus', 'en:fooDir/foo1.kmx')])
|
|
self.mockRestartIbus.assert_not_called()
|
|
|
|
def test_InstallKeyboardsToGnome_SingleKbMultipleLanguages(self):
|
|
# Setup
|
|
mockGnomeKeyboardsUtilInstance = self.mockGnomeKeyboardsUtilClass.return_value
|
|
mockGnomeKeyboardsUtilInstance.read_input_sources.return_value = [('xkb', 'en')]
|
|
keyboards = [{'id': 'foo1', 'languages': [{'id': 'en'}, {'id': 'fr'}]}]
|
|
# Execute
|
|
InstallKmp()._install_keyboards_to_gnome(keyboards, 'fooDir')
|
|
# Verify
|
|
mockGnomeKeyboardsUtilInstance.write_input_sources.assert_called_once_with(
|
|
[('xkb', 'en'), ('ibus', 'en:fooDir/foo1.kmx')])
|
|
self.mockRestartIbus.assert_not_called()
|
|
|
|
def test_InstallKeyboardsToGnome_SingleKbMultipleLanguages_GivenLanguage(self):
|
|
# Setup
|
|
mockGnomeKeyboardsUtilInstance = self.mockGnomeKeyboardsUtilClass.return_value
|
|
mockGnomeKeyboardsUtilInstance.read_input_sources.return_value = [('xkb', 'en')]
|
|
keyboards = [{'id': 'foo1', 'languages': [{'id': 'en'}, {'id': 'fr'}]}]
|
|
# Execute
|
|
InstallKmp()._install_keyboards_to_gnome(keyboards, 'fooDir', 'fr')
|
|
# Verify
|
|
mockGnomeKeyboardsUtilInstance.write_input_sources.assert_called_once_with(
|
|
[('xkb', 'en'), ('ibus', 'fr:fooDir/foo1.kmx')])
|
|
self.mockRestartIbus.assert_not_called()
|
|
|
|
def test_InstallKeyboardsToGnome_SingleKbMultipleLanguages_OtherLanguage(self):
|
|
# Setup
|
|
mockGnomeKeyboardsUtilInstance = self.mockGnomeKeyboardsUtilClass.return_value
|
|
mockGnomeKeyboardsUtilInstance.read_input_sources.return_value = [('xkb', 'en')]
|
|
keyboards = [{'id': 'foo1', 'languages': [{'id': 'en'}, {'id': 'fr'}]}]
|
|
# Execute
|
|
InstallKmp()._install_keyboards_to_gnome(keyboards, 'fooDir', 'de')
|
|
# Verify
|
|
mockGnomeKeyboardsUtilInstance.write_input_sources.assert_called_once_with(
|
|
[('xkb', 'en'), ('ibus', 'de:fooDir/foo1.kmx')])
|
|
self.mockRestartIbus.assert_not_called()
|
|
|
|
|
|
class NormalizeLanguageTests(InstallKmpBase):
|
|
def test_normalizeLanguage(self):
|
|
# Setup
|
|
languages = [
|
|
{'id': 'de'},
|
|
{'id': 'esi-Latn'},
|
|
{'id': 'dyo'},
|
|
{'id': 'fuh-Arab'}
|
|
]
|
|
|
|
for testcase in [
|
|
{'given': 'de', 'expected': 'de'},
|
|
{'given': 'esi', 'expected': 'esi'},
|
|
{'given': 'esi-Latn', 'expected': 'esi'},
|
|
{'given': 'es', 'expected': None},
|
|
{'given': 'en', 'expected': None},
|
|
{'given': None, 'expected': None},
|
|
# #3399
|
|
{'given': 'dyo-latn', 'expected': 'dyo'},
|
|
{'given': 'dyo', 'expected': 'dyo'},
|
|
{'given': 'fuh-Arab', 'expected': 'fuh-Arab'},
|
|
{'given': 'fuh', 'expected': None},
|
|
]:
|
|
with self.subTest(data=testcase):
|
|
# Execute
|
|
result = InstallKmp()._normalize_language(languages, testcase['given'])
|
|
|
|
# Verify
|
|
self.assertEqual(result, testcase['expected'])
|
|
|
|
def test_normalizeLanguage_noLanguages(self):
|
|
# Setup
|
|
languages = []
|
|
|
|
# Execute
|
|
result = InstallKmp()._normalize_language(languages, 'en')
|
|
|
|
# Verify
|
|
self.assertEqual(result, '')
|
|
|
|
|
|
class InstallKmpTests(InstallKmpBase):
|
|
def _createEmptyKmp(self, workdir):
|
|
kmpfile = os.path.join(workdir, 'foo.kmp')
|
|
with open(kmpfile, 'w') as file:
|
|
file.write('')
|
|
return kmpfile
|
|
|
|
def _createKmpJson(self, packagedir, fileVersionString):
|
|
with open(os.path.join(packagedir, 'kmp.json'), 'w') as file:
|
|
file.write('''{
|
|
"system": {
|
|
"keymanDeveloperVersion": "15.0"
|
|
''' + fileVersionString + '''
|
|
},
|
|
"files": [ {
|
|
"name": "khmer_angkor.kmx",
|
|
"description": "Keyboard Khmer Angkor"
|
|
}, {
|
|
"name": "kmp.json",
|
|
"description": "Package information (JSON)"
|
|
} ],
|
|
"keyboards": [ {
|
|
"name": "Khmer Angkor",
|
|
"id": "khmer_angkor",
|
|
"version": "1.1",
|
|
"languages": [ {
|
|
"name": "Central Khmer (Khmer, Cambodia)",
|
|
"id": "km"
|
|
} ]}
|
|
]}''')
|
|
|
|
def test_InstallKmp_FutureKeymanVersion(self):
|
|
# Setup
|
|
workdir = tempfile.TemporaryDirectory()
|
|
packagedir = tempfile.TemporaryDirectory()
|
|
self.mockGetKeyboardDir.return_value = packagedir.name
|
|
kmpfile = self._createEmptyKmp(workdir.name)
|
|
self._createKmpJson(packagedir.name, ', "fileVersion": "99.0"')
|
|
|
|
# Execute
|
|
with self.assertRaises(InstallError) as context:
|
|
InstallKmp()._install_kmp(kmpfile, 'km', InstallLocation.User)
|
|
|
|
# Verify
|
|
self.assertTrue('foo.kmp requires Keyman 99.0 or higher' in context.exception.message)
|
|
self.mockInstallToIbus.assert_not_called()
|
|
|
|
# Teardown
|
|
workdir.cleanup()
|
|
packagedir.cleanup()
|
|
|
|
def test_InstallKmp(self):
|
|
for testcase in [
|
|
{'name': 'PreviousKeymanVersion', 'fileVersion': ', "fileVersion": "7.0"'},
|
|
{'name': 'SameKeymanVersion', 'fileVersion': f', "fileVersion": "{__version__}"'},
|
|
{'name': 'NoFileVersion', 'fileVersion': ''}
|
|
]:
|
|
with self.subTest(msg=testcase['name'], data=testcase['fileVersion']):
|
|
# Setup
|
|
self.mockInstallToIbus.reset_mock()
|
|
workdir = tempfile.TemporaryDirectory()
|
|
packagedir = tempfile.TemporaryDirectory()
|
|
self.mockGetKeyboardDir.return_value = packagedir.name
|
|
kmpfile = self._createEmptyKmp(workdir.name)
|
|
self._createKmpJson(packagedir.name, testcase['fileVersion'])
|
|
|
|
with patch('keyman_config.install_kmp.process_keyboard_data') as mock:
|
|
method = mock.return_value
|
|
method.return_value = None
|
|
|
|
# Execute
|
|
InstallKmp()._install_kmp(kmpfile, 'km', InstallLocation.User)
|
|
|
|
# Verify
|
|
self.mockInstallToIbus.assert_called_once()
|
|
|
|
# Teardown
|
|
workdir.cleanup()
|
|
packagedir.cleanup()
|
|
|
|
|
|
class InstallKeyboardsTests(InstallKmpBase):
|
|
def test_InstallKeyboards_NoLang(self):
|
|
# Setup
|
|
mockCustomKeyboardsInstance = self.mockCustomKeyboardsClass.return_value
|
|
mockCustomKeyboardsInstance.get.return_value = None
|
|
keyboards = [{'id': 'foo1', 'languages': [{'id': 'en'}, {'id': 'fr'}]}]
|
|
# Execute
|
|
InstallKmp()._install_keyboards(keyboards, 'fooDir', None)
|
|
# Verify
|
|
self.mockInstallToIbus.assert_called_once_with(ANY, 'en:fooDir/foo1.kmx')
|
|
mockCustomKeyboardsInstance.add.assert_not_called()
|
|
|
|
def test_InstallKeyboards_LangInKeyboard(self):
|
|
# Setup
|
|
keyboards = [{'id': 'foo1', 'languages': [{'id': 'en'}, {'id': 'fr'}]}]
|
|
mockCustomKeyboardsInstance = self.mockCustomKeyboardsClass.return_value
|
|
mockCustomKeyboardsInstance.get.return_value = None
|
|
# Execute
|
|
InstallKmp()._install_keyboards(keyboards, 'fooDir', 'fr')
|
|
# Verify
|
|
self.mockInstallToIbus.assert_called_once_with(ANY, 'fr:fooDir/foo1.kmx')
|
|
mockCustomKeyboardsInstance.add.assert_not_called()
|
|
|
|
def test_InstallKeyboards_CustomLang(self):
|
|
# Setup
|
|
mockCustomKeyboardsInstance = self.mockCustomKeyboardsClass.return_value
|
|
mockCustomKeyboardsInstance.get.return_value = None
|
|
keyboards = [{'id': 'foo1', 'languages': [{'id': 'en'}, {'id': 'fr'}]}]
|
|
# Execute
|
|
InstallKmp()._install_keyboards(keyboards, 'fooDir', 'mul')
|
|
# Verify
|
|
self.mockInstallToIbus.assert_called_once_with(ANY, 'mul:fooDir/foo1.kmx')
|
|
mockCustomKeyboardsInstance.add.assert_called_once_with('mul:fooDir/foo1.kmx')
|
|
|
|
|
|
class AddCustomKeyboardTests(InstallKmpBase):
|
|
def test_AddCustomKeyboard_NoLang(self):
|
|
# Setup
|
|
mockCustomKeyboardsInstance = self.mockCustomKeyboardsClass.return_value
|
|
keyboard = {'id': 'foo1'}
|
|
# Execute
|
|
language = InstallKmp()._add_custom_keyboard(keyboard, 'fooDir', None)
|
|
# Verify
|
|
self.assertEqual(language, None)
|
|
mockCustomKeyboardsInstance.add.assert_not_called()
|
|
|
|
def test_AddCustomKeyboard_Add(self):
|
|
# Setup
|
|
mockCustomKeyboardsInstance = self.mockCustomKeyboardsClass.return_value
|
|
keyboard = {'id': 'foo1'}
|
|
# Execute
|
|
language = InstallKmp()._add_custom_keyboard(keyboard, 'fooDir', 'mul')
|
|
# Verify
|
|
self.assertEqual(language, 'mul')
|
|
mockCustomKeyboardsInstance.add.assert_called_once_with('mul:fooDir/foo1.kmx')
|