ibus-table/SOURCES/add-a-gui-test.patch
2021-09-09 19:03:27 +00:00

1817 lines
68 KiB
Diff
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

diff -Nru ibus-table-1.9.18/configure.ac ibus-table-1.9.18.new/configure.ac
--- ibus-table-1.9.18/configure.ac 2020-07-22 15:02:24.341755774 +0200
+++ ibus-table-1.9.18.new/configure.ac 2020-07-22 15:03:04.097344610 +0200
@@ -54,6 +54,15 @@
AM_GNU_GETTEXT([external])
AM_GNU_GETTEXT_VERSION(0.16.1)
+AC_ARG_ENABLE([installed-tests],
+ [AS_HELP_STRING([--enable-installed-tests],
+ [Enable to install tests])],
+ [enable_installed_tests=$enableval],
+ [enable_installed_tests=no]
+)
+
+AM_CONDITIONAL([ENABLE_INSTALLED_TESTS], [test x"$enable_installed_tests" = x"yes"])
+
# OUTPUT files
AC_CONFIG_FILES([po/Makefile.in
Makefile
diff -Nru ibus-table-1.9.18/tests/.gitignore ibus-table-1.9.18.new/tests/.gitignore
--- ibus-table-1.9.18/tests/.gitignore 2020-07-22 15:02:24.349755691 +0200
+++ ibus-table-1.9.18.new/tests/.gitignore 2020-07-22 15:11:24.740159555 +0200
@@ -1,5 +1,5 @@
run_tests
-run_tests.log
-run_tests.trs
-test-suite.log
+*.log
+*.trs
+*.tap
__pycache__/
diff -Nru ibus-table-1.9.18/tests/Makefile.am ibus-table-1.9.18.new/tests/Makefile.am
--- ibus-table-1.9.18/tests/Makefile.am 2020-07-22 15:02:24.349755691 +0200
+++ ibus-table-1.9.18.new/tests/Makefile.am 2020-07-22 15:04:28.298473415 +0200
@@ -19,20 +19,58 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#
-TESTS = run_tests
+TESTS = \
+ test_it.py \
+ test_0_gtk.py \
+ $(NULL)
+
+check_SCRIPTS = run_tests
+
+LOG_COMPILER = $(builddir)/run_tests
+
+TESTS_ENVIRONMENT = \
+ IBUS_TABLE_LOCATION=../
+
+test_meta_in = meta.test.in
+test_metas =
+
+if ENABLE_INSTALLED_TESTS
+test_metas += $(patsubst %.py, %.test, $(TESTS))
+test_source_DATA = $(test_metas)
+test_sourcedir = $(datadir)/installed-tests/ibus-table
+test_exec_SCRIPTS = \
+ $(TESTS) \
+ gtkcases.py \
+ mock_engine.py \
+ run_tests \
+ $(NULL)
+test_execdir = $(libexecdir)/installed-tests/ibus-table
+
+$(test_metas): $(test_meta_in)
+ @TEST_EXEC=`echo $@ | sed -e 's&\.test&\.py&'`; \
+ sed -e "s&@TEST_EXECDIR@&$(test_execdir)&g" \
+ -e "s&@TEST_EXEC@&$$TEST_EXEC&g" $< > $@.tmp; \
+ mv $@.tmp $@; \
+ $(NULL)
+endif
run_tests: run_tests.in
sed -e 's&@PYTHON_BIN@&$(PYTHON)&g' \
+ -e 's&@PKGDATADIR@&$(pkgdatadir)&g' \
-e 's&@SRCDIR@&$(srcdir)&g' $< > $@
chmod +x $@
EXTRA_DIST = \
- run_tests.in \
- test_it.py \
+ $(test_meta_in) \
__init__.py \
+ gtkcases.py \
+ mock_engine.py \
+ run_tests.in \
+ $(TESTS) \
$(NULL)
CLEANFILES = \
+ $(test_metas) \
run_tests \
$(NULL)
diff -Nru ibus-table-1.9.18/tests/gtkcases.py ibus-table-1.9.18.new/tests/gtkcases.py
--- ibus-table-1.9.18/tests/gtkcases.py 1970-01-01 01:00:00.000000000 +0100
+++ ibus-table-1.9.18.new/tests/gtkcases.py 2020-07-22 15:03:04.097344610 +0200
@@ -0,0 +1,38 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+
+# 'init' has one array which is [keysym, keycode, modifier] and to be run
+# before the main tests. E.g.
+# Ctrl-space to enable Hiragana mode
+#
+# 'tests' cases are the main test cases.
+# 'preedit' case runs to create a preedit text.
+# 'lookup' case runs to update a lookup table.
+# 'commit' case runs to commit the preedit text.
+# 'result' case is the expected output.
+# 'preedit', 'lookup', 'commit' can choose the type of either 'string' or 'keys'
+# 'string' type is a string sequence which does not need modifiers
+
+from gi import require_version as gi_require_version
+gi_require_version('IBus', '1.0')
+from gi.repository import IBus
+
+TestCases = {
+ #'init': [IBus.KEY_j, 0, IBus.ModifierType.CONTROL_MASK],
+ 'tests': [
+ {'preedit': {'string': 'a'},
+ 'lookup': {'keys': [[IBus.KEY_Down, 0, 0]]},
+ 'commit': {'keys': [[IBus.KEY_space, 0, 0]]},
+ 'result': {'string': '区'}
+ },
+ {'preedit': {'string': 'ijgl'},
+ 'commit': {'keys': [[IBus.KEY_space, 0, 0]]},
+ 'result': {'string': '漫画'}
+ },
+ {'preedit': {'string': 'wgl'},
+ 'lookup': {'keys': [[IBus.KEY_Down, 0, 0]]},
+ 'commit': {'keys': [[IBus.KEY_space, 0, 0]]},
+ 'result': {'string': '全国'}
+ },
+ ]
+}
diff -Nru ibus-table-1.9.18/tests/meta.test.in ibus-table-1.9.18.new/tests/meta.test.in
--- ibus-table-1.9.18/tests/meta.test.in 1970-01-01 01:00:00.000000000 +0100
+++ ibus-table-1.9.18.new/tests/meta.test.in 2020-07-22 15:03:04.097344610 +0200
@@ -0,0 +1,4 @@
+[Test]
+Type=session
+Exec=@TEST_EXECDIR@/run_tests @TEST_EXEC@
+Output=TAP
diff -Nru ibus-table-1.9.18/tests/mock_engine.py ibus-table-1.9.18.new/tests/mock_engine.py
--- ibus-table-1.9.18/tests/mock_engine.py 1970-01-01 01:00:00.000000000 +0100
+++ ibus-table-1.9.18.new/tests/mock_engine.py 2020-07-22 15:07:00.649895226 +0200
@@ -0,0 +1,241 @@
+# ibus-table - The Tables engine for IBus
+#
+# Copyright (c) 2018-2020 Mike FABIAN <mfabian@redhat.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+'''
+Define some mock classes for the unittests.
+'''
+
+from gi import require_version
+require_version('IBus', '1.0')
+from gi.repository import IBus
+
+class MockEngine:
+ def __init__(self, engine_name = '', connection = None, object_path = ''):
+ self.mock_auxiliary_text = ''
+ self.mock_preedit_text = ''
+ self.mock_preedit_text_cursor_pos = 0
+ self.mock_preedit_text_visible = True
+ self.mock_committed_text = ''
+ self.mock_committed_text_cursor_pos = 0
+ self.client_capabilities = (
+ IBus.Capabilite.PREEDIT_TEXT
+ | IBus.Capabilite.AUXILIARY_TEXT
+ | IBus.Capabilite.LOOKUP_TABLE
+ | IBus.Capabilite.FOCUS
+ | IBus.Capabilite.PROPERTY)
+ # There are lots of weird problems with surrounding text
+ # which makes this hard to test. Therefore this mock
+ # engine does not try to support surrounding text, i.e.
+ # we omit “| IBus.Capabilite.SURROUNDING_TEXT” here.
+
+ def update_auxiliary_text(self, text, visible):
+ self.mock_auxiliary_text = text.text
+
+ def hide_auxiliary_text(self):
+ pass
+
+ def hide_preedit_text(self):
+ pass
+
+ def commit_text(self, text):
+ self.mock_committed_text = (
+ self.mock_committed_text[
+ :self.mock_committed_text_cursor_pos]
+ + text.text
+ + self.mock_committed_text[
+ self.mock_committed_text_cursor_pos:])
+ self.mock_committed_text_cursor_pos += len(text.text)
+
+ def forward_key_event(self, val, code, state):
+ if (val == IBus.KEY_Left
+ and self.mock_committed_text_cursor_pos > 0):
+ self.mock_committed_text_cursor_pos -= 1
+ return
+ unicode = IBus.keyval_to_unicode(val)
+ if unicode:
+ self.mock_committed_text = (
+ self.mock_committed_text[
+ :self.mock_committed_text_cursor_pos]
+ + unicode
+ + self.mock_committed_text[
+ self.mock_committed_text_cursor_pos:])
+ self.mock_committed_text_cursor_pos += len(unicode)
+
+ def update_lookup_table(self, table, visible):
+ pass
+
+ def update_preedit_text(self, text, cursor_pos, visible):
+ self.mock_preedit_text = text.get_text()
+ self.mock_preedit_text_cursor_pos = cursor_pos
+ self.mock_preedit_text_visible = visible
+
+ def register_properties(self, property_list):
+ pass
+
+ def update_property(self, property):
+ pass
+
+ def hide_lookup_table(self):
+ pass
+
+class MockLookupTable:
+ def __init__(self, page_size = 9, cursor_pos = 0, cursor_visible = False, round = True):
+ self.clear()
+ self.mock_page_size = page_size
+ self.mock_cursor_pos = cursor_pos
+ self.mock_cursor_visible = cursor_visible
+ self.cursor_visible = cursor_visible
+ self.mock_round = round
+ self.mock_candidates = []
+ self.mock_labels = []
+ self.mock_page_number = 0
+
+ def clear(self):
+ self.mock_candidates = []
+ self.mock_cursor_pos = 0
+
+ def set_page_size(self, size):
+ self.mock_page_size = size
+
+ def get_page_size(self):
+ return self.mock_page_size
+
+ def set_round(self, round):
+ self.mock_round = round
+
+ def set_cursor_pos(self, pos):
+ self.mock_cursor_pos = pos
+
+ def get_cursor_pos(self):
+ return self.mock_cursor_pos
+
+ def get_cursor_in_page(self):
+ return (self.mock_cursor_pos
+ - self.mock_page_size * self.mock_page_number)
+
+ def set_cursor_visible(self, visible):
+ self.mock_cursor_visible = visible
+ self.cursor_visible = visible
+
+ def cursor_down(self):
+ if len(self.mock_candidates):
+ self.mock_cursor_pos += 1
+ self.mock_cursor_pos %= len(self.mock_candidates)
+
+ def cursor_up(self):
+ if len(self.mock_candidates):
+ if self.mock_cursor_pos > 0:
+ self.mock_cursor_pos -= 1
+ else:
+ self.mock_cursor_pos = len(self.mock_candidates) - 1
+
+ def page_down(self):
+ if len(self.mock_candidates):
+ self.mock_page_number += 1
+ self.mock_cursor_pos += self.mock_page_size
+
+ def page_up(self):
+ if len(self.mock_candidates):
+ if self.mock_page_number > 0:
+ self.mock_page_number -= 1
+ self.mock_cursor_pos -= self.mock_page_size
+
+ def set_orientation(self, orientation):
+ self.mock_orientation = orientation
+
+ def get_number_of_candidates(self):
+ return len(self.mock_candidates)
+
+ def append_candidate(self, candidate):
+ self.mock_candidates.append(candidate.get_text())
+
+ def get_candidate(self, index):
+ return self.mock_candidates[index]
+
+ def get_number_of_candidates(self):
+ return len(self.mock_candidates)
+
+ def append_label(self, label):
+ self.mock_labels.append(label.get_text())
+
+class MockPropList:
+ def __init__(self, *args, **kwargs):
+ self._mock_proplist = []
+
+ def append(self, property):
+ self._mock_proplist.append(property)
+
+ def get(self, index):
+ if index >= 0 and index < len(self._mock_proplist):
+ return self._mock_proplist[index]
+ else:
+ return None
+
+ def update_property(self, property):
+ pass
+
+class MockProperty:
+ def __init__(self,
+ key='',
+ prop_type=IBus.PropType.RADIO,
+ label=IBus.Text.new_from_string(''),
+ symbol=IBus.Text.new_from_string(''),
+ icon='',
+ tooltip=IBus.Text.new_from_string(''),
+ sensitive=True,
+ visible=True,
+ state=IBus.PropState.UNCHECKED,
+ sub_props=None):
+ self.mock_property_key = key
+ self.mock_property_prop_type = prop_type
+ self.mock_property_label = label.get_text()
+ self.mock_property_symbol = symbol.get_text()
+ self.mock_property_icon = icon
+ self.mock_property_tooltip = tooltip.get_text()
+ self.mock_property_sensitive = sensitive
+ self.mock_property_visible = visible
+ self.mock_property_state = state
+ self.mock_property_sub_props = sub_props
+
+ def set_label(self, ibus_text):
+ self.mock_property_label = ibus_text.get_text()
+
+ def set_symbol(self, ibus_text):
+ self.mock_property_symbol = ibus_text.get_text()
+
+ def set_tooltip(self, ibus_text):
+ self.mock_property_tooltip = ibus_text.get_text()
+
+ def set_icon(self, icon_path):
+ self.mock_property_icon = icon_path
+
+ def set_sensitive(self, sensitive):
+ self.mock_property_sensitive = sensitive
+
+ def set_visible(self, visible):
+ self.mock_property_visible = visible
+
+ def set_state(self, state):
+ self.mock_property_state = state
+
+ def set_sub_props(self, proplist):
+ self.mock_property_sub_props = proplist
+
+ def get_key(self):
+ return self.mock_property_key
diff -Nru ibus-table-1.9.18/tests/run_tests.in ibus-table-1.9.18.new/tests/run_tests.in
--- ibus-table-1.9.18/tests/run_tests.in 2020-07-22 15:02:24.349755691 +0200
+++ ibus-table-1.9.18.new/tests/run_tests.in 2020-07-22 15:04:42.505326247 +0200
@@ -15,239 +15,47 @@
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-#
+# License along with this library. If not, see <http://www.gnu.org/licenses/>
-import os
import sys
+import os
import unittest
-from gi import require_version
-require_version('IBus', '1.0')
-from gi.repository import IBus
-
-# -- Define some mock classes for the tests ----------------------------------
-class MockEngine:
- def __init__(self, engine_name = '', connection = None, object_path = ''):
- self.mock_auxiliary_text = ''
- self.mock_preedit_text = ''
- self.mock_preedit_text_cursor_pos = 0
- self.mock_preedit_text_visible = True
- self.mock_committed_text = ''
- self.mock_committed_text_cursor_pos = 0
- self.client_capabilities = (
- IBus.Capabilite.PREEDIT_TEXT
- | IBus.Capabilite.AUXILIARY_TEXT
- | IBus.Capabilite.LOOKUP_TABLE
- | IBus.Capabilite.FOCUS
- | IBus.Capabilite.PROPERTY)
- # There are lots of weird problems with surrounding text
- # which makes this hard to test. Therefore this mock
- # engine does not try to support surrounding text, i.e.
- # we omit “| IBus.Capabilite.SURROUNDING_TEXT” here.
-
- def update_auxiliary_text(self, text, visible):
- self.mock_auxiliary_text = text.text
-
- def hide_auxiliary_text(self):
- pass
-
- def commit_text(self, text):
- self.mock_committed_text = (
- self.mock_committed_text[
- :self.mock_committed_text_cursor_pos]
- + text.text
- + self.mock_committed_text[
- self.mock_committed_text_cursor_pos:])
- self.mock_committed_text_cursor_pos += len(text.text)
-
- def forward_key_event(self, val, code, state):
- if (val == IBus.KEY_Left
- and self.mock_committed_text_cursor_pos > 0):
- self.mock_committed_text_cursor_pos -= 1
- return
- unicode = IBus.keyval_to_unicode(val)
- if unicode:
- self.mock_committed_text = (
- self.mock_committed_text[
- :self.mock_committed_text_cursor_pos]
- + unicode
- + self.mock_committed_text[
- self.mock_committed_text_cursor_pos:])
- self.mock_committed_text_cursor_pos += len(unicode)
-
- def update_lookup_table(self, table, visible):
- pass
-
- def update_preedit_text(self, text, cursor_pos, visible):
- self.mock_preedit_text = text.get_text()
- self.mock_preedit_text_cursor_pos = cursor_pos
- self.mock_preedit_text_visible = visible
-
- def register_properties(self, property_list):
- pass
-
- def update_property(self, property):
- pass
-
- def hide_lookup_table(self):
- pass
-
-class MockLookupTable:
- def __init__(self, page_size = 9, cursor_pos = 0, cursor_visible = False, round = True):
- self.clear()
- self.mock_page_size = page_size
- self.mock_cursor_pos = cursor_pos
- self.mock_cursor_visible = cursor_visible
- self.cursor_visible = cursor_visible
- self.mock_round = round
- self.mock_candidates = []
- self.mock_labels = []
- self.mock_page_number = 0
-
- def clear(self):
- self.mock_candidates = []
- self.mock_cursor_pos = 0
-
- def set_page_size(self, size):
- self.mock_page_size = size
-
- def get_page_size(self):
- return self.mock_page_size
-
- def set_round(self, round):
- self.mock_round = round
-
- def set_cursor_pos(self, pos):
- self.mock_cursor_pos = pos
-
- def get_cursor_pos(self):
- return self.mock_cursor_pos
-
- def get_cursor_in_page(self):
- return (self.mock_cursor_pos
- - self.mock_page_size * self.mock_page_number)
-
- def set_cursor_visible(self, visible):
- self.mock_cursor_visible = visible
- self.cursor_visible = visible
-
- def cursor_down(self):
- if len(self.mock_candidates):
- self.mock_cursor_pos += 1
- self.mock_cursor_pos %= len(self.mock_candidates)
-
- def cursor_up(self):
- if len(self.mock_candidates):
- if self.mock_cursor_pos > 0:
- self.mock_cursor_pos -= 1
- else:
- self.mock_cursor_pos = len(self.mock_candidates) - 1
-
- def page_down(self):
- if len(self.mock_candidates):
- self.mock_page_number += 1
- self.mock_cursor_pos += self.mock_page_size
-
- def page_up(self):
- if len(self.mock_candidates):
- if self.mock_page_number > 0:
- self.mock_page_number -= 1
- self.mock_cursor_pos -= self.mock_page_size
-
- def set_orientation(self, orientation):
- self.mock_orientation = orientation
-
- def get_number_of_candidates(self):
- return len(self.mock_candidates)
-
- def append_candidate(self, candidate):
- self.mock_candidates.append(candidate.get_text())
-
- def get_candidate(self, index):
- return self.mock_candidates[index]
-
- def get_number_of_candidates(self):
- return len(self.mock_candidates)
-
- def append_label(self, label):
- self.mock_labels.append(label.get_text())
-
-class MockPropList:
- def __init__(self, *args, **kwargs):
- self._mock_proplist = []
-
- def append(self, property):
- self._mock_proplist.append(property)
-
- def get(self, index):
- if index >= 0 and index < len(self._mock_proplist):
- return self._mock_proplist[index]
- else:
- return None
-
- def update_property(self, property):
- pass
-
-class MockProperty:
- def __init__(self,
- key='',
- prop_type=IBus.PropType.RADIO,
- label=IBus.Text.new_from_string(''),
- symbol=IBus.Text.new_from_string(''),
- icon='',
- tooltip=IBus.Text.new_from_string(''),
- sensitive=True,
- visible=True,
- state=IBus.PropState.UNCHECKED,
- sub_props=None):
- self.mock_property_key = key
- self.mock_property_prop_type = prop_type
- self.mock_property_label = label.get_text()
- self.mock_property_symbol = symbol.get_text()
- self.mock_property_icon = icon
- self.mock_property_tooltip = tooltip.get_text()
- self.mock_property_sensitive = sensitive
- self.mock_property_visible = visible
- self.mock_property_state = state
- self.mock_property_sub_props = sub_props
-
- def set_label(self, ibus_text):
- self.mock_property_label = ibus_text.get_text()
-
- def set_symbol(self, ibus_text):
- self.mock_property_symbol = ibus_text.get_text()
-
- def set_tooltip(self, ibus_text):
- self.mock_property_tooltip = ibus_text.get_text()
-
- def set_sensitive(self, sensitive):
- self.mock_property_sensitive = sensitive
-
- def set_visible(self, visible):
- self.mock_property_visible = visible
-
- def set_state(self, state):
- self.mock_property_state = state
-
- def set_sub_props(self, proplist):
- self.mock_property_sub_props = proplist
-
- def get_key(self):
- return self.mock_property_key
-
-# -- Monkey patch the environment with the mock classes ----------------------
-sys.modules["gi.repository.IBus"].Engine = MockEngine
-sys.modules["gi.repository.IBus"].LookupTable = MockLookupTable
-sys.modules["gi.repository.IBus"].Property = MockProperty
-sys.modules["gi.repository.IBus"].PropList = MockPropList
+# pip3 install tap.py --user
+IMPORT_TAP_SUCCESSFUL = False
+try:
+ from tap import TAPTestRunner
+ IMPORT_TAP_SUCCESSFUL = True
+except (ImportError,):
+ pass
+
+if 'IBUS_TABLE_LOCATION' in os.environ:
+ location_path = os.environ['IBUS_TABLE_LOCATION']
+ if location_path != None and location_path != '':
+ engine_path = os.path.join(location_path, 'engine')
+ sys.path.append(engine_path)
+sys.path.append('@PKGDATADIR@/engine')
# -- Load and run our unit tests ---------------------------------------------
-os.environ['IBUS_TABLE_DEBUG_LEVEL'] = '255'
+pattern = 'test*.py'
+start_dir = os.path.dirname(__file__)
+if len(sys.argv) > 1:
+ pattern = sys.argv[-1]
+ dir = os.path.dirname(pattern)
+ pattern = os.path.basename(pattern)
+ if dir != '.':
+ start_dir = os.path.join(start_dir, dir)
loader = unittest.TestLoader()
-suite = loader.discover(".")
-runner = unittest.TextTestRunner(stream = sys.stderr, verbosity = 255)
+suite = loader.discover(start_dir=start_dir, pattern=pattern)
+
+if IMPORT_TAP_SUCCESSFUL:
+ runner = TAPTestRunner(stream=sys.stderr, verbosity=255)
+ runner.set_outdir('.')
+ runner.set_format('Hi: {method_name} - {short_description}')
+ runner.set_combined(True)
+else:
+ runner = unittest.TextTestRunner(stream=sys.stderr, verbosity=255)
+
result = runner.run(suite)
if result.failures or result.errors:
diff -Nru ibus-table-1.9.18/tests/test_0_gtk.py ibus-table-1.9.18.new/tests/test_0_gtk.py
--- ibus-table-1.9.18/tests/test_0_gtk.py 1970-01-01 01:00:00.000000000 +0100
+++ ibus-table-1.9.18.new/tests/test_0_gtk.py 2020-07-22 15:09:02.734630566 +0200
@@ -0,0 +1,441 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+#
+# ibus-table - The Tables engine for IBus
+#
+# Copyright (c) 2020 Takao Fujiwara <takao.fujiwara1@gmail.com>
+# Copyright (c) 2020 Mike FABIAN <mfabian@redhat.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library. If not, see <http://www.gnu.org/licenses/>
+'''
+This file implements the test cases using GTK GUI
+'''
+# “Wrong continued indentation”: pylint: disable=bad-continuation
+# pylint: disable=attribute-defined-outside-init
+# pylint: disable=missing-function-docstring
+# pylint: disable=missing-class-docstring
+# pylint: disable=global-statement
+# pylint: disable=wrong-import-order
+# pylint: disable=wrong-import-position
+
+import argparse
+import os
+import signal
+import sys
+import unittest
+
+from gi import require_version as gi_require_version
+gi_require_version('GLib', '2.0')
+gi_require_version('Gdk', '3.0')
+gi_require_version('Gio', '2.0')
+gi_require_version('Gtk', '3.0')
+gi_require_version('IBus', '1.0')
+from gi.repository import GLib
+from gi.repository import Gdk
+from gi.repository import Gio
+from gi.repository import Gtk
+from gi.repository import IBus
+
+# Get more verbose output in the test log:
+os.environ['IBUS_TABLE_DEBUG_LEVEL'] = '255'
+
+sys.path.insert(0, "../engine")
+IMPORT_TABLE_SUCCESSFUL = False
+try:
+ import table
+ IMPORT_TABLE_SUCCESSFUL = True
+except (ImportError,):
+ pass
+IMPORT_TABSQLITEDB_SUCCESSFUL = False
+try:
+ import tabsqlitedb
+ IMPORT_TABSQLITEDB_SUCCESSFUL = True
+except (ImportError,):
+ pass
+# FIXME:
+#sys.path.pop(0)
+
+DONE_EXIT = True
+ENGINE_NAME = 'wubi-jidian86'
+
+from gtkcases import TestCases
+
+# Need to flush the output against Gtk.main()
+def printflush(sentence):
+ try:
+ print(sentence, flush=True)
+ except IOError:
+ pass
+
+def printerr(sentence):
+ try:
+ print(sentence, flush=True, file=sys.stderr)
+ except IOError:
+ pass
+
+@unittest.skipUnless(
+ os.path.isfile(
+ os.path.join('/usr/share/ibus-table/tables', ENGINE_NAME + '.db')),
+ '%s.db is not installed.' % ENGINE_NAME + '.db')
+@unittest.skipUnless(
+ 'XDG_SESSION_TYPE' in os.environ
+ and os.environ['XDG_SESSION_TYPE'] in ('x11', 'wayland'),
+ 'XDG_SESSION_TYPE is neither "x11" nor "wayland".')
+@unittest.skipIf(Gdk.Display.open('') is None, 'Display cannot be opened.')
+class SimpleGtkTestCase(unittest.TestCase):
+ global DONE_EXIT
+ global ENGINE_NAME
+ ENGINE_PATH = '/com/redhat/IBus/engines/table/Test/Engine'
+
+ @classmethod
+ def setUpClass(cls):
+ cls._flag = False
+ IBus.init()
+ cls._gsettings = Gio.Settings(
+ schema='org.freedesktop.ibus.engine.table',
+ path='/org/freedesktop/ibus/engine/table/%s/' % ENGINE_NAME)
+ cls._orig_chinesemode = cls._gsettings.get_int('chinesemode')
+ signums = [getattr(signal, s, None) for s in
+ 'SIGINT SIGTERM SIGHUP'.split()]
+ for signum in filter(None, signums):
+ original_handler = signal.getsignal(signum)
+ GLib.unix_signal_add(GLib.PRIORITY_HIGH,
+ signum,
+ cls.signal_handler,
+ (signum, original_handler))
+ @classmethod
+ def tearDownClass(cls):
+ cls._gsettings.set_int('chinesemode', cls._orig_chinesemode)
+
+ @classmethod
+ def signal_handler(cls, user_data):
+ (signum, original_handler) = user_data
+ cls.tearDownClass()
+ Gtk.main_quit()
+ signal.signal(signum, original_handler)
+ cls._flag = True
+ assert False, 'signal received: ' + str(signum)
+
+ def setUp(self):
+ self.__id = 0
+ self.__rerun = False
+ self.__test_index = 0
+ self.__preedit_index = 0
+ self.__lookup_index = 0
+ self.__inserted_text = ''
+ self.__commit_done = False
+ self.__reset_coming = False
+ self._gsettings.set_int('chinesemode', 4)
+
+ def register_ibus_engine(self):
+ self.__bus = IBus.Bus()
+ if not self.__bus.is_connected():
+ self.fail('ibus-daemon is not running')
+ return False
+ self.__bus.get_connection().signal_subscribe(
+ 'org.freedesktop.DBus',
+ 'org.freedesktop.DBus',
+ 'NameOwnerChanged',
+ '/org/freedesktop/DBus',
+ None,
+ 0,
+ self.__bus_signal_cb,
+ self.__bus)
+ self.__factory = IBus.Factory(
+ object_path=IBus.PATH_FACTORY,
+ connection=self.__bus.get_connection())
+ self.__factory.connect('create-engine', self.__create_engine_cb)
+ self.__component = IBus.Component(
+ name='org.freedesktop.IBus.Table.Test',
+ description='Test Table Component',
+ version='1.0',
+ license='GPL',
+ author=('Mike FABIAN <mfabian@redhat.com>, '
+ + 'Caius "kaio" CHANCE <caius.chance@gmail.com>'),
+ homepage='http://mike-fabian.github.io/ibus-table/',
+ command_line='',
+ textdomain='ibus-table')
+ desc = IBus.EngineDesc(
+ name=ENGINE_NAME,
+ longname='Test Table %s' % ENGINE_NAME,
+ description='Test Table Component',
+ language='t',
+ license='GPL',
+ author=('Mike FABIAN <mfabian@redonat.com>, '
+ + 'Caius "kaio" CHANCE <caius.chance@gmail.com>'),
+ icon='',
+ symbol='T')
+ self.__component.add_engine(desc)
+ self.__bus.register_component(self.__component)
+ self.__bus.request_name('org.freedesktop.IBus.Table.Test', 0)
+ return True
+
+ def __bus_signal_cb(self, connection, sender_name, object_path,
+ interface_name, signal_name, parameters,
+ user_data):
+ if signal_name == 'NameOwnerChanged':
+ pass
+ if signal_name == 'UpdateLookupTable':
+ table = self.__engine._editor.get_lookup_table()
+ if table.get_number_of_candidates() == 0:
+ return
+ self.__lookup_test()
+
+ def __create_engine_cb(self, factory, engine_name):
+ if engine_name != ENGINE_NAME:
+ return None
+ if (not IMPORT_TABLE_SUCCESSFUL
+ or not IMPORT_TABSQLITEDB_SUCCESSFUL):
+ with self.subTest(i='create-engine'):
+ self.fail('NG: ibus-table not installed?')
+ Gtk.main_quit()
+ return None
+ self.__id += 1
+ object_path = '%s/%d' % (self.ENGINE_PATH, self.__id)
+ db_dir = '/usr/share/ibus-table/tables'
+ db_file = os.path.join(db_dir, engine_name + '.db')
+ database = tabsqlitedb.TabSqliteDb(filename=db_file, user_db=':memory:')
+ self.__engine = table.TabEngine(
+ self.__bus,
+ object_path,
+ database)
+ self.__engine.connect('focus-in', self.__engine_focus_in)
+ self.__engine.connect('focus-out', self.__engine_focus_out)
+ # FIXME: Need to connect 'reset' after TabEngine.clear_all_input_and_preedit()
+ # is called.
+ self.__engine.connect_after('reset', self.__engine_reset)
+ self.__bus.get_connection().signal_subscribe(
+ None,
+ IBus.INTERFACE_ENGINE,
+ 'UpdateLookupTable',
+ object_path,
+ None,
+ 0,
+ self.__bus_signal_cb,
+ self.__bus)
+ return self.__engine
+
+ def __engine_focus_in(self, _engine):
+ if self.__test_index == len(TestCases['tests']):
+ if DONE_EXIT:
+ Gtk.main_quit()
+ return
+ # Workaround because focus-out resets the preedit text
+ # ibus_bus_set_global_engine() calls bus_input_context_set_engine()
+ # twice and it causes bus_engine_proxy_focus_out()
+ if self.__rerun:
+ self.__rerun = False
+ self.__main_test()
+
+ def __engine_focus_out(self, _engine):
+ self.__rerun = True
+ self.__test_index = 0
+ self.__entry.set_text('')
+
+ def __engine_reset(self, _engine):
+ if self.__reset_coming:
+ self.__reset_coming = False
+ self.__main_test()
+
+ def __entry_focus_in_event_cb(self, entry, event):
+ if self.__test_index == len(TestCases['tests']):
+ if DONE_EXIT:
+ Gtk.main_quit()
+ return False
+ self.__bus.set_global_engine_async(ENGINE_NAME,
+ -1, None, self.__set_engine_cb)
+ return False
+
+ def __set_engine_cb(self, _object, res):
+ with self.subTest(i=self.__test_index):
+ if not self.__bus.set_global_engine_async_finish(res):
+ self.fail('set engine failed.')
+ return
+ # rerun always happen?
+ #self.__main_test()
+
+ def __get_test_condition_length(self, tag):
+ tests = TestCases['tests'][self.__test_index]
+ try:
+ cases = tests[tag]
+ except KeyError:
+ return -1
+ case_type = list(cases.keys())[0]
+ return len(cases[case_type])
+
+ def __entry_preedit_changed_cb(self, entry, preedit_str):
+ if len(preedit_str) == 0:
+ return
+ if self.__test_index == len(TestCases['tests']):
+ if DONE_EXIT:
+ Gtk.main_quit()
+ return
+ self.__preedit_index += 1
+ if self.__preedit_index != self.__get_test_condition_length('preedit'):
+ return
+ if self.__get_test_condition_length('lookup') > 0:
+ return
+ self.__run_cases('commit')
+
+ def __main_test(self):
+ self.__preedit_index = 0
+ self.__lookup_index = 0
+ self.__commit_done = False
+ self.__run_cases('preedit')
+
+ def __lookup_test(self):
+ lookup_length = self.__get_test_condition_length('lookup')
+ # Need to return again even if all the lookup is finished
+ # until the final Engine.update_preedit() is called.
+ if self.__lookup_index > lookup_length:
+ return
+ self.__run_cases('lookup',
+ self.__lookup_index,
+ self.__lookup_index + 1)
+ if self.__lookup_index < lookup_length:
+ self.__lookup_index += 1
+ return
+ self.__lookup_index += 1
+ self.__run_cases('commit')
+
+ def __run_cases(self, tag, start=-1, end=-1):
+ tests = TestCases['tests'][self.__test_index]
+ if tests is None:
+ return
+ try:
+ cases = tests[tag]
+ except KeyError:
+ return
+ case_type = list(cases.keys())[0]
+ i = 0
+ if case_type == 'string':
+ printflush('test step: %s sequences: "%s"'
+ % (tag, str(cases['string'])))
+ for character in cases['string']:
+ if start >= 0 and i < start:
+ i += 1
+ continue
+ if 0 <= end <= i:
+ break
+ self.__typing(ord(character), 0, 0)
+ i += 1
+ if case_type == 'keys':
+ if start == -1 and end == -1:
+ printflush('test step: %s sequences: %s'
+ % (tag, str(cases['keys'])))
+ for key in cases['keys']:
+ if start >= 0 and i < start:
+ i += 1
+ continue
+ if 0 <= end <= i:
+ break
+ if start != -1 or end != -1:
+ printflush('test step: %s sequences: [0x%X, 0x%X, 0x%X]'
+ % (tag, key[0], key[1], key[2]))
+ self.__typing(key[0], key[1], key[2])
+ i += 1
+
+ def __typing(self, keyval, keycode, modifiers):
+ self.__engine.emit('process-key-event', keyval, keycode, modifiers)
+ modifiers |= IBus.ModifierType.RELEASE_MASK
+ self.__engine.emit('process-key-event', keyval, keycode, modifiers)
+
+ def __buffer_inserted_text_cb(self, buffer, position, chars, nchars):
+ tests = TestCases['tests'][self.__test_index]
+ cases = tests['commit']
+ case_type = list(cases.keys())[0]
+ if case_type == 'keys':
+ # space key is sent separatedly later
+ if cases['keys'][0] == [IBus.KEY_space, 0, 0]:
+ self.__inserted_text += chars
+ # FIXME: Return key emits 'reset' signal in GTK and it calls
+ # TableEngine.clear_all_input_and_preedit().
+ elif cases['keys'][0] == [IBus.KEY_Return, 0, 0] or \
+ cases['keys'][0] == [IBus.KEY_KP_Enter, 0, 0] or \
+ cases['keys'][0] == [IBus.KEY_ISO_Enter, 0, 0] or \
+ cases['keys'][0] == [IBus.KEY_Escape, 0, 0]:
+ self.__inserted_text = chars
+ self.__reset_coming = True
+ else:
+ self.__inserted_text = chars
+ cases = tests['result']
+ if cases['string'] == self.__inserted_text:
+ printflush('OK: %d "%s"'
+ % (self.__test_index, self.__inserted_text))
+ else:
+ if DONE_EXIT:
+ Gtk.main_quit()
+ with self.subTest(i=self.__test_index):
+ self.fail('NG: %d "%s" "%s"'
+ % (self.__test_index, str(cases['string']),
+ self.__inserted_text))
+ self.__inserted_text = ''
+ self.__test_index += 1
+ if self.__test_index == len(TestCases['tests']):
+ if DONE_EXIT:
+ Gtk.main_quit()
+ return
+ self.__commit_done = True
+ self.__entry.set_text('')
+ if not self.__reset_coming:
+ self.__main_test()
+
+ def create_window(self):
+ window = Gtk.Window(type=Gtk.WindowType.TOPLEVEL)
+ self.__entry = entry = Gtk.Entry()
+ window.connect('destroy', Gtk.main_quit)
+ entry.connect('focus-in-event', self.__entry_focus_in_event_cb)
+ entry.connect('preedit-changed', self.__entry_preedit_changed_cb)
+ buffer = entry.get_buffer()
+ buffer.connect('inserted-text', self.__buffer_inserted_text_cb)
+ window.add(entry)
+ window.show_all()
+
+ def main(self): # pylint: disable=no-self-use
+ # Some ATK relative warnings are called during launching GtkWindow.
+ flags = GLib.log_set_always_fatal(GLib.LogLevelFlags.LEVEL_CRITICAL)
+ Gtk.main()
+ GLib.log_set_always_fatal(flags)
+
+ def test_typing(self):
+ if not self.register_ibus_engine():
+ sys.exit(-1)
+ self.create_window()
+ self.main()
+ if self._flag:
+ self.fail('NG: signal failure')
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('-k', '--keep', action='store_true',
+ help='keep this GtkWindow after test is done')
+ parser.add_argument('-F', '--unittest-failfast', action='store_true',
+ help='stop on first fail or error in unittest')
+ parser.add_argument('-H', '--unittest-help', action='store_true',
+ help='show unittest help message and exit')
+ args, unittest_args = parser.parse_known_args()
+ sys.argv[1:] = unittest_args
+ if args.keep:
+ global DONE_EXIT
+ DONE_EXIT = False
+ if args.unittest_failfast:
+ sys.argv.append('-f')
+ if args.unittest_help:
+ sys.argv.append('-h')
+ unittest.main()
+
+ unittest.main()
+
+if __name__ == '__main__':
+ main()
diff -Nru ibus-table-1.9.18/tests/test_it.py ibus-table-1.9.18.new/tests/test_it.py
--- ibus-table-1.9.18/tests/test_it.py 2020-07-22 15:02:24.350755681 +0200
+++ ibus-table-1.9.18.new/tests/test_it.py 2020-07-22 15:05:43.128698254 +0200
@@ -1,6 +1,5 @@
-# -*- coding: utf-8 -*-
-# vim:et sts=4 sw=4
-#
+#!/usr/bin/python3
+
# ibus-table - The Tables engine for IBus
#
# Copyright (c) 2018 Mike FABIAN <mfabian@redhat.com>
@@ -26,19 +25,41 @@
import sys
import os
-import unicodedata
import unittest
-import subprocess
+import importlib
+import mock
from gi import require_version
require_version('IBus', '1.0')
from gi.repository import IBus
+# Get more verbose output in the test log:
+os.environ['IBUS_TABLE_DEBUG_LEVEL'] = '255'
+
+# Monkey patch the environment with the mock classes:
+from mock_engine import MockEngine
+from mock_engine import MockLookupTable
+from mock_engine import MockProperty
+from mock_engine import MockPropList
+
sys.path.insert(0, "../engine")
-from table import *
+import table
import tabsqlitedb
-import it_util
-#sys.path.pop(0)
+import ibus_table_location
+sys.path.pop(0)
+
+ENGINE_PATCHER = mock.patch.object(
+ IBus, 'Engine', new=MockEngine)
+LOOKUP_TABLE_PATCHER = mock.patch.object(
+ IBus, 'LookupTable', new=MockLookupTable)
+PROPERTY_PATCHER = mock.patch.object(
+ IBus, 'Property', new=MockProperty)
+PROP_LIST_PATCHER = mock.patch.object(
+ IBus, 'PropList', new=MockPropList)
+IBUS_ENGINE = IBus.Engine
+IBUS_LOOKUP_TABLE = IBus.LookupTable
+IBUS_PROPERTY = IBus.Property
+IBUS_PROP_LIST = IBus.PropList
ENGINE = None
TABSQLITEDB = None
@@ -56,6 +77,8 @@
ORIG_AUTOWILDCARD_MODE = None
ORIG_SINGLE_WILDCARD_CHAR = None
ORIG_MULTI_WILDCARD_CHAR = None
+ORIG_PINYIN_MODE = None
+ORIG_SUGGESTION_MODE = None
def backup_original_settings():
global ENGINE
@@ -73,6 +96,8 @@
global ORIG_AUTOWILDCARD_MODE
global ORIG_SINGLE_WILDCARD_CHAR
global ORIG_MULTI_WILDCARD_CHAR
+ global ORIG_PINYIN_MODE
+ global ORIG_SUGGESTION_MODE
ORIG_INPUT_MODE = ENGINE.get_input_mode()
ORIG_CHINESE_MODE = ENGINE.get_chinese_mode()
ORIG_LETTER_WIDTH = ENGINE.get_letter_width()
@@ -87,6 +112,8 @@
ORIG_AUTOWILDCARD_MODE = ENGINE.get_autowildcard_mode()
ORIG_SINGLE_WILDCARD_CHAR = ENGINE.get_single_wildcard_char()
ORIG_MULTI_WILDCARD_CHAR = ENGINE.get_multi_wildcard_char()
+ ORIG_PINYIN_MODE = ENGINE.get_pinyin_mode()
+ ORIG_SUGGESTION_MODE = ENGINE.get_suggestion_mode()
def restore_original_settings():
global ENGINE
@@ -104,6 +131,8 @@
global ORIG_AUTOWILDCARD_MODE
global ORIG_SINGLE_WILDCARD_CHAR
global ORIG_MULTI_WILDCARD_CHAR
+ global ORIG_PINYIN_MODE
+ global ORIG_SUGGESTION_MODE
ENGINE.set_input_mode(ORIG_INPUT_MODE)
ENGINE.set_chinese_mode(ORIG_CHINESE_MODE)
ENGINE.set_letter_width(ORIG_LETTER_WIDTH[0], input_mode=0)
@@ -120,14 +149,16 @@
ENGINE.set_autowildcard_mode(ORIG_AUTOWILDCARD_MODE)
ENGINE.set_single_wildcard_char(ORIG_SINGLE_WILDCARD_CHAR)
ENGINE.set_multi_wildcard_char(ORIG_MULTI_WILDCARD_CHAR)
+ ENGINE.set_pinyin_mode(ORIG_PINYIN_MODE)
+ ENGINE.set_suggestion_mode(ORIG_SUGGESTION_MODE)
def set_default_settings():
global ENGINE
global TABSQLITEDB
ENGINE.set_input_mode(mode=1)
- chinese_mode = 0
+ chinese_mode = 4
language_filter = TABSQLITEDB.ime_properties.get('language_filter')
- if language_filter in ['cm0', 'cm1', 'cm2', 'cm3', 'cm4']:
+ if language_filter in ('cm0', 'cm1', 'cm2', 'cm3', 'cm4'):
chinese_mode = int(language_filter[-1])
ENGINE.set_chinese_mode(mode=chinese_mode)
@@ -136,7 +167,7 @@
'def_full_width_letter')
if def_full_width_letter:
letter_width_mode = (def_full_width_letter.lower() == u'true')
- ENGINE.set_letter_width(mode=letter_width_mode, input_mode=0)
+ ENGINE.set_letter_width(mode=False, input_mode=0)
ENGINE.set_letter_width(mode=letter_width_mode, input_mode=1)
punctuation_width_mode = False
@@ -144,7 +175,7 @@
'def_full_width_punct')
if def_full_width_punct:
punctuation_width_mode = (def_full_width_punct.lower() == u'true')
- ENGINE.set_punctuation_width(mode=punctuation_width_mode, input_mode=0)
+ ENGINE.set_punctuation_width(mode=False, input_mode=0)
ENGINE.set_punctuation_width(mode=punctuation_width_mode, input_mode=1)
always_show_lookup_mode = True
@@ -161,7 +192,8 @@
select_keys_csv = TABSQLITEDB.ime_properties.get('select_keys')
# select_keys_csv is something like: "1,2,3,4,5,6,7,8,9,0"
if select_keys_csv:
- ENGINE.set_page_size(len(select_keys_csv.split(",")))
+ page_size = len(select_keys_csv.split(","))
+ ENGINE.set_page_size(page_size)
onechar = False
ENGINE.set_onechar_mode(onechar)
@@ -223,28 +255,98 @@
multi_wildcard_char = multi_wildcard_char[0]
ENGINE.set_multi_wildcard_char(multi_wildcard_char)
+ ENGINE.set_pinyin_mode(False)
+ ENGINE.set_suggestion_mode(False)
+
def set_up(engine_name):
+ '''
+ Setup an ibus table engine
+
+ :param engine_name: The name of the engine to setup
+ :type engine_name: String
+ :return: True if the engine could be setup successfully, False if not.
+ :rtype: Boolean
+ '''
+ global ENGINE_PATCHER
+ global LOOKUP_TABLE_PATCHER
+ global PROPERTY_PATCHER
+ global PROP_LIST_PATCHER
+ global IBUS_ENGINE
+ global IBUS_LOOKUP_TABLE
+ global IBUS_PROPERTY
+ global IBUS_PROP_LIST
global TABSQLITEDB
global ENGINE
+ ENGINE_PATCHER.start()
+ LOOKUP_TABLE_PATCHER.start()
+ PROPERTY_PATCHER.start()
+ PROP_LIST_PATCHER.start()
+ assert IBus.Engine is not IBUS_ENGINE
+ assert IBus.Engine is MockEngine
+ assert IBus.LookupTable is not IBUS_LOOKUP_TABLE
+ assert IBus.LookupTable is MockLookupTable
+ assert IBus.Property is not IBUS_PROPERTY
+ assert IBus.Property is MockProperty
+ assert IBus.PropList is not IBUS_PROP_LIST
+ assert IBus.PropList is MockPropList
+ # Reload the table module so that the patches
+ # are applied to TabEngine:
+ sys.path.insert(0, '../engine')
+ importlib.reload(table)
+ sys.path.pop(0)
bus = IBus.Bus()
db_dir = '/usr/share/ibus-table/tables'
db_file = os.path.join(db_dir, engine_name + '.db')
- TABSQLITEDB = tabsqlitedb.tabsqlitedb(
+ if not os.path.isfile(db_file):
+ TABSQLITEDB = None
+ ENGINE = None
+ tear_down()
+ return False
+ TABSQLITEDB = tabsqlitedb.TabSqliteDb(
filename=db_file, user_db=':memory:')
- ENGINE = tabengine(
+ ENGINE = table.TabEngine(
bus,
'/com/redhat/IBus/engines/table/%s/engine/0' %engine_name,
TABSQLITEDB,
- unit_test = True)
+ unit_test=True)
backup_original_settings()
set_default_settings()
+ return True
def tear_down():
+ global ENGINE_PATCHER
+ global LOOKUP_TABLE_PATCHER
+ global PROPERTY_PATCHER
+ global PROP_LIST_PATCHER
+ global IBUS_ENGINE
+ global IBUS_LOOKUP_TABLE
+ global IBUS_PROPERTY
+ global IBUS_PROP_LIST
+ global TABSQLITEDB
+ global ENGINE
+ if ENGINE:
restore_original_settings()
+ TABSQLITEDB = None
+ ENGINE = None
+ # Remove the patches from the IBus stuff:
+ ENGINE_PATCHER.stop()
+ LOOKUP_TABLE_PATCHER.stop()
+ PROPERTY_PATCHER.stop()
+ PROP_LIST_PATCHER.stop()
+ assert IBus.Engine is IBUS_ENGINE
+ assert IBus.Engine is not MockEngine
+ assert IBus.LookupTable is IBUS_LOOKUP_TABLE
+ assert IBus.LookupTable is not MockLookupTable
+ assert IBus.Property is IBUS_PROPERTY
+ assert IBus.Property is not MockProperty
+ assert IBus.PropList is IBUS_PROP_LIST
+ assert IBus.PropList is not MockPropList
-class Wubi_Jidian86TestCase(unittest.TestCase):
+class WubiJidian86TestCase(unittest.TestCase):
def setUp(self):
- set_up('wubi-jidian86')
+ engine_name = 'wubi-jidian86'
+ if not set_up(engine_name):
+ self.skipTest('Could not setup “%s”, skipping test.' % engine_name)
def tearDown(self):
tear_down()
@@ -257,7 +359,81 @@
ENGINE.do_process_key_event(IBus.KEY_space, 0, 0)
self.assertEqual(ENGINE.mock_committed_text, '工')
- def test_commit_to_preedit_and_switching_to_pinyin_and_defining_a_phrase(self):
+ def test_pinyin_mode(self):
+ # Pinyin mode is False by default:
+ self.assertEqual(ENGINE.get_pinyin_mode(), False)
+ ENGINE.do_process_key_event(IBus.KEY_a, 0, 0)
+ self.assertEqual(ENGINE.mock_preedit_text, '工')
+ ENGINE.do_process_key_event(IBus.KEY_space, 0, 0)
+ self.assertEqual(ENGINE.mock_preedit_text, '')
+ self.assertEqual(ENGINE.mock_committed_text, '工')
+ ENGINE.set_pinyin_mode(True)
+ ENGINE.do_process_key_event(IBus.KEY_a, 0, 0)
+ self.assertEqual(ENGINE.mock_preedit_text, '爱')
+ ENGINE.do_process_key_event(IBus.KEY_space, 0, 0)
+ self.assertEqual(ENGINE.mock_preedit_text, '')
+ self.assertEqual(ENGINE.mock_committed_text, '工爱')
+ ENGINE.set_pinyin_mode(False)
+ ENGINE.do_process_key_event(IBus.KEY_a, 0, 0)
+ self.assertEqual(ENGINE.mock_preedit_text, '工')
+ ENGINE.do_process_key_event(IBus.KEY_space, 0, 0)
+ self.assertEqual(ENGINE.mock_preedit_text, '')
+ self.assertEqual(ENGINE.mock_committed_text, '工爱工')
+
+ def test_suggestion_mode(self):
+ if not ENGINE._ime_sg:
+ self.skipTest("This engine does not have a suggestion mode.")
+ # Suggestion mode is False by default:
+ self.assertEqual(ENGINE.get_suggestion_mode(), False)
+ self.assertEqual(ENGINE.get_pinyin_mode(), False)
+ ENGINE.do_process_key_event(IBus.KEY_a, 0, 0)
+ self.assertEqual(ENGINE.mock_preedit_text, '工')
+ ENGINE.do_process_key_event(IBus.KEY_space, 0, 0)
+ self.assertEqual(ENGINE.mock_preedit_text, '')
+ self.assertEqual(ENGINE.mock_committed_text, '工')
+ self.assertEqual(ENGINE._editor._lookup_table.mock_candidates, [])
+ ENGINE.set_suggestion_mode(True)
+ ENGINE.do_process_key_event(IBus.KEY_a, 0, 0)
+ self.assertEqual(ENGINE.mock_preedit_text, '工')
+ ENGINE.do_process_key_event(IBus.KEY_space, 0, 0)
+ self.assertEqual(ENGINE.mock_preedit_text, '')
+ self.assertEqual(ENGINE.mock_committed_text, '工工')
+ self.assertEqual(ENGINE._editor._lookup_table.mock_candidates,
+ ['工作人员 673 0',
+ '工作会议 310 0',
+ '工作报告 267 0',
+ '工人阶级 146 0',
+ '工作重点 78 0',
+ '工作小组 73 0',
+ '工业企业 71 0',
+ '工业大学 69 0',
+ '工作单位 61 0',
+ '工业生产 58 0'])
+ ENGINE.do_process_key_event(IBus.KEY_space, 0, 0)
+ self.assertEqual(ENGINE.mock_preedit_text, '')
+ self.assertEqual(ENGINE.mock_committed_text, '工工作人员')
+ ENGINE.set_pinyin_mode(True)
+ ENGINE.do_process_key_event(IBus.KEY_a, 0, 0)
+ self.assertEqual(ENGINE.mock_preedit_text, '爱')
+ ENGINE.do_process_key_event(IBus.KEY_space, 0, 0)
+ self.assertEqual(ENGINE.mock_preedit_text, '')
+ self.assertEqual(ENGINE.mock_committed_text, '工工作人员爱')
+ self.assertEqual(ENGINE._editor._lookup_table.mock_candidates,
+ ['爱因斯坦 1109 0',
+ '爱情故事 519 0',
+ '爱国主义 191 0',
+ '爱尔兰语 91 0',
+ '爱好和平 62 0',
+ '爱情小说 58 0',
+ '爱不释手 39 0',
+ '爱国热情 35 0',
+ '爱莫能助 34 0',
+ '爱理不理 32 0'])
+ ENGINE.do_process_key_event(IBus.KEY_space, 0, 0)
+ self.assertEqual(ENGINE.mock_preedit_text, '')
+ self.assertEqual(ENGINE.mock_committed_text, '工工作人员爱因斯坦')
+
+ def test_commit_to_preedit_switching_to_pinyin_defining_a_phrase(self):
ENGINE.do_process_key_event(IBus.KEY_a, 0, 0)
# commit to preëdit needs a press and release of either
# the left or the right shift key:
@@ -324,7 +500,8 @@
IBus.KEY_Shift_L, 0,
IBus.ModifierType.SHIFT_MASK | IBus.ModifierType.RELEASE_MASK)
self.assertEqual(ENGINE.mock_preedit_text, '工了你好以在')
- # Move right two characters in the preëdit (triggers a commit to preëdit):
+ # Move right two characters in the preëdit
+ # (triggers a commit to preëdit):
ENGINE.do_process_key_event(IBus.KEY_Right, 0, 0)
ENGINE.do_process_key_event(IBus.KEY_Right, 0, 0)
self.assertEqual(ENGINE.mock_auxiliary_text, 'd dhf dhfd\t#: abwd')
@@ -353,9 +530,88 @@
ENGINE.do_process_key_event(IBus.KEY_space, 0, 0)
self.assertEqual(ENGINE.mock_committed_text, '工了你好以在工了你好以在')
+ def test_chinese_mode(self):
+ ENGINE.set_chinese_mode(mode=0) # show simplified Chinese only
+ ENGINE.do_process_key_event(IBus.KEY_c, 0, 0)
+ self.assertEqual(ENGINE._editor._lookup_table.mock_candidates,
+ ['以 418261033 0',
+ '能 ex 1820000000 0',
+ '能 exx 1820000000 0',
+ '对 fy 1200000000 0',
+ '又 cc 729000000 0',
+ '又 ccc 729000000 0',
+ '通 ep 521000000 0',
+ '通 epk 521000000 0',
+ '台 kf 486000000 0',
+ '难忘 wyn 404000000 0'])
+ ENGINE.do_process_key_event(IBus.KEY_BackSpace, 0, 0)
+ self.assertEqual(ENGINE._editor._lookup_table.mock_candidates, [])
+ ENGINE.set_chinese_mode(mode=1) # show traditional Chinese only
+ ENGINE.do_process_key_event(IBus.KEY_c, 0, 0)
+ self.assertEqual(ENGINE._editor._lookup_table.mock_candidates,
+ ['以 418261033 0',
+ '能 ex 1820000000 0',
+ '能 exx 1820000000 0',
+ '又 cc 729000000 0',
+ '又 ccc 729000000 0',
+ '通 ep 521000000 0',
+ '通 epk 521000000 0',
+ '台 kf 486000000 0',
+ '能 e 306980312 0',
+ '能力 elt 274000000 0'])
+ ENGINE.do_process_key_event(IBus.KEY_BackSpace, 0, 0)
+ self.assertEqual(ENGINE._editor._lookup_table.mock_candidates, [])
+ ENGINE.set_chinese_mode(mode=2) # show simplified Chinese first
+ ENGINE.do_process_key_event(IBus.KEY_c, 0, 0)
+ self.assertEqual(ENGINE._editor._lookup_table.mock_candidates,
+ ['以 418261033 0',
+ '能 ex 1820000000 0',
+ '能 exx 1820000000 0',
+ '对 fy 1200000000 0',
+ '又 cc 729000000 0',
+ '又 ccc 729000000 0',
+ '通 ep 521000000 0',
+ '通 epk 521000000 0',
+ '台 kf 486000000 0',
+ '难忘 wyn 404000000 0'])
+ ENGINE.do_process_key_event(IBus.KEY_BackSpace, 0, 0)
+ self.assertEqual(ENGINE._editor._lookup_table.mock_candidates, [])
+ ENGINE.set_chinese_mode(mode=3) # show traditional Chinese first
+ ENGINE.do_process_key_event(IBus.KEY_c, 0, 0)
+ self.assertEqual(ENGINE._editor._lookup_table.mock_candidates,
+ ['以 418261033 0',
+ '能 ex 1820000000 0',
+ '能 exx 1820000000 0',
+ '又 cc 729000000 0',
+ '又 ccc 729000000 0',
+ '通 ep 521000000 0',
+ '通 epk 521000000 0',
+ '台 kf 486000000 0',
+ '能 e 306980312 0',
+ '能力 elt 274000000 0'])
+ ENGINE.do_process_key_event(IBus.KEY_BackSpace, 0, 0)
+ self.assertEqual(ENGINE._editor._lookup_table.mock_candidates, [])
+ ENGINE.set_chinese_mode(mode=4) # show all characters
+ ENGINE.do_process_key_event(IBus.KEY_c, 0, 0)
+ self.assertEqual(ENGINE._editor._lookup_table.mock_candidates,
+ ['以 418261033 0',
+ '能 ex 1820000000 0',
+ '能 exx 1820000000 0',
+ '对 fy 1200000000 0',
+ '又 cc 729000000 0',
+ '又 ccc 729000000 0',
+ '通 ep 521000000 0',
+ '通 epk 521000000 0',
+ '台 kf 486000000 0',
+ '难忘 wyn 404000000 0'])
+ ENGINE.do_process_key_event(IBus.KEY_BackSpace, 0, 0)
+ self.assertEqual(ENGINE._editor._lookup_table.mock_candidates, [])
+
class Stroke5TestCase(unittest.TestCase):
def setUp(self):
- set_up('stroke5')
+ engine_name = 'stroke5'
+ if not set_up(engine_name):
+ self.skipTest('Could not setup “%s”, skipping test.' % engine_name)
def tearDown(self):
tear_down()
@@ -372,9 +628,56 @@
ENGINE.do_process_key_event(IBus.KEY_space, 0, 0)
self.assertEqual(ENGINE.mock_committed_text, '的')
+class TelexTestCase(unittest.TestCase):
+ def setUp(self):
+ engine_name = 'telex'
+ if not set_up(engine_name):
+ self.skipTest('Could not setup “%s”, skipping test.' % engine_name)
+
+ def tearDown(self):
+ tear_down()
+
+ def test_dummy(self):
+ self.assertEqual(True, True)
+
+ def test_telex(self):
+ ENGINE.do_process_key_event(IBus.KEY_o, 0, 0)
+ self.assertEqual(ENGINE.mock_preedit_text, 'o')
+ self.assertEqual(ENGINE.mock_committed_text, '')
+ ENGINE.do_process_key_event(IBus.KEY_backslash, 0, 0)
+ self.assertEqual(ENGINE.mock_preedit_text, '')
+ self.assertEqual(ENGINE.mock_committed_text, 'o')
+ ENGINE.do_process_key_event(IBus.KEY_o, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_f, 0, 0)
+ self.assertEqual(ENGINE.mock_preedit_text, '')
+ self.assertEqual(ENGINE.mock_committed_text, 'oò')
+ ENGINE.do_process_key_event(IBus.KEY_o, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_o, 0, 0)
+ self.assertEqual(ENGINE.mock_preedit_text, 'ô')
+ self.assertEqual(ENGINE.mock_committed_text, 'oò')
+ ENGINE.do_process_key_event(IBus.KEY_backslash, 0, 0)
+ self.assertEqual(ENGINE.mock_preedit_text, '')
+ self.assertEqual(ENGINE.mock_committed_text, 'oòô')
+ ENGINE.do_process_key_event(IBus.KEY_o, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_o, 0, 0)
+ self.assertEqual(ENGINE.mock_preedit_text, 'ô')
+ self.assertEqual(ENGINE.mock_committed_text, 'oòô')
+ ENGINE.do_process_key_event(IBus.KEY_backslash, 0, 0)
+ self.assertEqual(ENGINE.mock_preedit_text, '')
+ self.assertEqual(ENGINE.mock_committed_text, 'oòôô')
+ ENGINE.do_process_key_event(IBus.KEY_o, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_o, 0, 0)
+ self.assertEqual(ENGINE.mock_preedit_text, 'ô')
+ self.assertEqual(ENGINE.mock_committed_text, 'oòôô')
+ ENGINE.do_process_key_event(IBus.KEY_j, 0, 0)
+ self.assertEqual(ENGINE.mock_preedit_text, '')
+ self.assertEqual(ENGINE.mock_committed_text, 'oòôôộ')
+
class TranslitTestCase(unittest.TestCase):
def setUp(self):
- set_up('translit')
+ engine_name ='translit'
+ if not set_up(engine_name):
+ self.skipTest('Could not setup “%s”, skipping test.' % engine_name)
def tearDown(self):
tear_down()
@@ -401,3 +704,215 @@
self.assertEqual(ENGINE.mock_preedit_text, 'с')
ENGINE.do_process_key_event(IBus.KEY_space, 0, 0)
self.assertEqual(ENGINE.mock_committed_text, 'шщс ')
+
+ def test_sh_multiple_match_slavic(self):
+ ENGINE.do_process_key_event(IBus.KEY_scaron, 0, 0)
+ self.assertEqual(ENGINE.mock_preedit_text, 'ш')
+ self.assertEqual(ENGINE.mock_committed_text, '')
+ ENGINE.do_process_key_event(IBus.KEY_h, 0, 0)
+ self.assertEqual(ENGINE.mock_preedit_text, '')
+ self.assertEqual(ENGINE.mock_committed_text, 'щ')
+ ENGINE.do_process_key_event(IBus.KEY_scaron, 0, 0)
+ self.assertEqual(ENGINE.mock_preedit_text, 'ш')
+ self.assertEqual(ENGINE.mock_committed_text, 'щ')
+ ENGINE.do_process_key_event(IBus.KEY_ccaron, 0, 0)
+ self.assertEqual(ENGINE.mock_preedit_text, '')
+ self.assertEqual(ENGINE.mock_committed_text, 'щщ')
+
+class Cangjie5TestCase(unittest.TestCase):
+ def setUp(self):
+ engine_name = 'cangjie5'
+ if not set_up(engine_name):
+ self.skipTest('Could not setup “%s”, skipping test.' % engine_name)
+
+ def tearDown(self):
+ tear_down()
+
+ def test_dummy(self):
+ self.assertEqual(True, True)
+
+ def test_single_char_commit_with_space(self):
+ ENGINE.do_process_key_event(IBus.KEY_a, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_space, 0, 0)
+ self.assertEqual(ENGINE.mock_committed_text, '日')
+
+ def test_type_one_char_and_check_auxiliary(self):
+ ENGINE.do_process_key_event(IBus.KEY_d, 0, 0)
+ self.assertEqual(ENGINE.mock_preedit_text, '木')
+ self.assertEqual(ENGINE._editor._lookup_table.mock_candidates[8],
+ '林 木 1000 0')
+ ENGINE.do_process_key_event(IBus.KEY_v, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_i, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_i, 0, 0)
+ self.assertEqual(ENGINE.mock_preedit_text, '機')
+ self.assertEqual(ENGINE.mock_auxiliary_text, '木女戈戈 (1 / 1)')
+ self.assertEqual(ENGINE._editor._lookup_table.mock_candidates,
+ ['機 1000 0'])
+ ENGINE.do_process_key_event(IBus.KEY_space, 0, 0)
+ self.assertEqual(ENGINE.mock_committed_text, '機')
+
+class IpaXSampaTestCase(unittest.TestCase):
+ def setUp(self):
+ engine_name = 'ipa-x-sampa'
+ if not set_up(engine_name):
+ self.skipTest('Could not setup “%s”, skipping test.' % engine_name)
+
+ def tearDown(self):
+ tear_down()
+
+ def test_dummy(self):
+ self.assertEqual(True, True)
+
+ def test_single_char_commit_with_space(self):
+ ENGINE.do_process_key_event(IBus.KEY_at, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_space, 0, 0)
+ self.assertEqual(ENGINE.mock_committed_text, 'ə ')
+
+ def test_single_char_commit_with_f3(self):
+ ENGINE.do_process_key_event(IBus.KEY_at, 0, 0)
+ self.assertEqual(ENGINE._editor._lookup_table.mock_candidates,
+ ['ə 0 0', 'ɘ \\ 0 0', 'ɚ ` 0 0'])
+ ENGINE.do_process_key_event(IBus.KEY_F3, 0, 0)
+ self.assertEqual(ENGINE.mock_committed_text, 'ɚ')
+
+class LatexTestCase(unittest.TestCase):
+ def setUp(self):
+ engine_name = 'latex'
+ if not set_up(engine_name):
+ self.skipTest('Could not setup “%s”, skipping test.' % engine_name)
+
+ def tearDown(self):
+ tear_down()
+
+ def test_dummy(self):
+ self.assertEqual(True, True)
+
+ def test_single_char_commit_with_space(self):
+ ENGINE.do_process_key_event(IBus.KEY_backslash, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_a, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_l, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_p, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_h, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_a, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_space, 0, 0)
+ self.assertEqual(ENGINE.mock_committed_text, 'α')
+
+ def test_single_char_commit_with_space_fraktur(self):
+ # needs ibus-table-others-1.3.10 which adds
+ # most of Unicode 9.0 block Mathematical Alphanumeric Symbols
+ ENGINE.do_process_key_event(IBus.KEY_backslash, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_m, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_a, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_t, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_h, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_f, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_r, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_a, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_k, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_F, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_space, 0, 0)
+ self.assertEqual(ENGINE.mock_committed_text, '𝔉')
+
+ def test_single_char_commit_with_f3(self):
+ ENGINE.do_process_key_event(IBus.KEY_backslash, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_b, 0, 0)
+ # Lookup table shows only the first page, subsequent
+ # pages are added on demand as a speed optimization:
+ self.assertEqual(ENGINE._editor._lookup_table.mock_candidates,
+ ['¯ ar 0 0',
+ '⊥ ot 0 0',
+ 'β eta 0 0',
+ 'ℶ eth 0 0',
+ '⋂ igcap 0 0',
+ ' igcup 0 0',
+ ' igvee 0 0',
+ '⋈ owtie 0 0',
+ '⊡ oxdot 0 0'])
+ ENGINE.do_process_key_event(IBus.KEY_F3, 0, 0)
+ self.assertEqual(ENGINE.mock_committed_text, 'β')
+ ENGINE.do_process_key_event(IBus.KEY_backslash, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_b, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_Page_Down, 0, 0)
+ self.assertEqual(ENGINE._editor._lookup_table.mock_candidates,
+ ['β eta 0 1', # user freq for β increased to 1
+ '¯ ar 0 0',
+ '⊥ ot 0 0',
+ 'ℶ eth 0 0',
+ '⋂ igcap 0 0',
+ ' igcup 0 0',
+ ' igvee 0 0',
+ '⋈ owtie 0 0',
+ '⊡ oxdot 0 0',
+ '• ullet 0 0',
+ '∙ ullet 0 0',
+ '≏ umpeq 0 0',
+ '∽ acksim 0 0',
+ '∵ ecause 0 0',
+ '≬ etween 0 0',
+ '⊞ oxplus 0 0',
+ '⊼ arwedge 0 0',
+ '⋀ igwedge 0 0'])
+ self.assertEqual(ENGINE._editor._lookup_table.get_cursor_pos(), 9)
+ ENGINE.do_process_key_event(IBus.KEY_Down, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_Down, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_Down, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_Down, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_Down, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_Down, 0, 0)
+ self.assertEqual(ENGINE._editor._lookup_table.get_cursor_pos(), 15)
+ self.assertEqual(ENGINE._editor._lookup_table.mock_candidates[0:18],
+ ['β eta 0 1', # user freq for β increased to 1
+ '¯ ar 0 0',
+ '⊥ ot 0 0',
+ 'ℶ eth 0 0',
+ '⋂ igcap 0 0',
+ ' igcup 0 0',
+ ' igvee 0 0',
+ '⋈ owtie 0 0',
+ '⊡ oxdot 0 0',
+ '• ullet 0 0',
+ '∙ ullet 0 0',
+ '≏ umpeq 0 0',
+ '∽ acksim 0 0',
+ '∵ ecause 0 0',
+ '≬ etween 0 0',
+ '⊞ oxplus 0 0',
+ '⊼ arwedge 0 0',
+ '⋀ igwedge 0 0'])
+ ENGINE.do_process_key_event(IBus.KEY_space, 0, 0)
+ self.assertEqual(ENGINE.mock_committed_text, 'β⊞')
+ ENGINE.do_process_key_event(IBus.KEY_backslash, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_b, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_Page_Down, 0, 0)
+ self.assertEqual(ENGINE._editor._lookup_table.mock_candidates,
+ ['β eta 0 1', # user freq for β increased to 1
+ '⊞ oxplus 0 1', # user freq for ⊞ increased to 1
+ '¯ ar 0 0',
+ '⊥ ot 0 0',
+ 'ℶ eth 0 0',
+ '⋂ igcap 0 0',
+ ' igcup 0 0',
+ ' igvee 0 0',
+ '⋈ owtie 0 0',
+ '⊡ oxdot 0 0',
+ '• ullet 0 0',
+ '∙ ullet 0 0',
+ '≏ umpeq 0 0',
+ '∽ acksim 0 0',
+ '∵ ecause 0 0',
+ '≬ etween 0 0',
+ '⊼ arwedge 0 0',
+ '⋀ igwedge 0 0'])
+ self.assertEqual(ENGINE._editor._lookup_table.get_cursor_pos(), 9)
+ ENGINE.do_process_key_event(IBus.KEY_Down, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_Down, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_Down, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_Down, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_Down, 0, 0)
+ ENGINE.do_process_key_event(IBus.KEY_Down, 0, 0)
+ self.assertEqual(ENGINE._editor._lookup_table.get_cursor_pos(), 15)
+ ENGINE.do_process_key_event(IBus.KEY_space, 0, 0)
+ self.assertEqual(ENGINE.mock_committed_text, 'β⊞≬')
+
+if __name__ == '__main__':
+ unittest.main()