on xenial help sign in
Update the autopilot tests to work with the new dash app.

Approved by: Michał Sawicz

commitaf3058bc1a95656ff3cdb779b810f91ee2323544 authorLeo Arias <leo.arias@canonical.com> dateTue 5 Aug 2014, 12:06 (12 years ago) parentf9796474843223
12 files changed+385−174
tests/autopilot/unity8/application_lifecycle/tests/test_application_lifecycle.py+1−1 tests/autopilot/unity8/application_lifecycle/tests/test_url_dispatcher.py+3−2 tests/autopilot/unity8/fixture_setup.py+64 tests/autopilot/unity8/process_helpers.py+89−20 tests/autopilot/unity8/shell/emulators/dash.py+21−8 tests/autopilot/unity8/shell/emulators/greeter.py+4−1 tests/autopilot/unity8/shell/emulators/main_window.py+34−20 tests/autopilot/unity8/shell/tests/__init__.py+141−48 tests/autopilot/unity8/shell/tests/test_emulators.py+7−18 tests/autopilot/unity8/shell/tests/test_lock_screen.py+7−47 tests/autopilot/unity8/shell/tests/test_notifications.py+12−7 tests/autopilot/unity8/shell/tests/test_upstart.py+2−2
tests/autopilot/unity8/application_lifecycle/tests/test_application_lifecycle.py+1−1
@@ -106,7 +106,7 @@ class ApplicationLifecycleTests(tests.ApplicationLifeCycleTestCase):
106106 self.assert_current_focused_application(application_name)
107107
108108 self.main_window.show_dash_swiping()
109− self.assert_current_focused_application('')
109+ self.assert_current_focused_application('unity8-dash')
110110
111111 process_helpers.lock_unity()
112112 greeter = self.main_window.get_greeter()
tests/autopilot/unity8/application_lifecycle/tests/test_url_dispatcher.py+3−2
@@ -39,7 +39,8 @@ class URLDispatcherTestCase(tests.ApplicationLifeCycleTestCase):
3939 desktop_file_name = os.path.basename(desktop_file_path)
4040 application_name, _ = os.path.splitext(desktop_file_name)
4141
42− self.assertEqual('', self.main_window.get_current_focused_app_id())
42+ self.assertEqual(
43+ 'unity8-dash', self.main_window.get_current_focused_app_id())
4344 self.addCleanup(os.system, 'pkill qmlscene')
4445
4546 subprocess.check_call(
@@ -47,4 +48,4 @@ class URLDispatcherTestCase(tests.ApplicationLifeCycleTestCase):
4748 self.assert_current_focused_application(application_name)
4849
4950 self.main_window.show_dash_swiping()
50− self.assert_current_focused_application('')
51+ self.assert_current_focused_application('unity8-dash')
tests/autopilot/unity8/fixture_setup.pynew file+64
@@ -0,0 +1,64 @@
1+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2+#
3+# Unity Autopilot Test Suite
4+# Copyright (C) 2014 Canonical
5+#
6+# This program is free software: you can redistribute it and/or modify
7+# it under the terms of the GNU General Public License as published by
8+# the Free Software Foundation, either version 3 of the License, or
9+# (at your option) any later version.
10+#
11+# This program is distributed in the hope that it will be useful,
12+# but WITHOUT ANY WARRANTY; without even the implied warranty of
13+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+# GNU General Public License for more details.
15+#
16+# You should have received a copy of the GNU General Public License
17+# along with this program. If not, see <http://www.gnu.org/licenses/>.
18+#
19+
20+import fixtures
21+from autopilot import introspection
22+
23+from unity8 import process_helpers
24+from unity8.shell import emulators
25+
26+
27+class LaunchDashApp(fixtures.Fixture):
28+
29+ """Fixture to launch the Dash app."""
30+
31+ def __init__(self, binary_path, variables):
32+ """Initialize an instance.
33+
34+ :param str binary_path: The path to the Dash app binary.
35+ :param variables: The variables to use when launching the app.
36+ :type variables: A dictionary.
37+
38+ """
39+ super(LaunchDashApp, self).__init__()
40+ self.binary_path = binary_path
41+ self.variables = variables
42+
43+ def setUp(self):
44+ """Launch the dash app when the fixture is used."""
45+ super(LaunchDashApp, self).setUp()
46+ self.addCleanup(self.stop_application)
47+ self.application_proxy = self.launch_application()
48+
49+ def launch_application(self):
50+ binary_arg = 'BINARY={}'.format(self.binary_path)
51+ testability_arg = 'QT_LOAD_TESTABILITY={}'.format(1)
52+ env_args = [
53+ '{}={}'.format(key, value) for key, value in self.variables.items()
54+ ]
55+ all_args = [binary_arg, testability_arg] + env_args
56+
57+ pid = process_helpers.start_job('unity8-dash', *all_args)
58+ return introspection.get_proxy_object_for_existing_process(
59+ pid=pid,
60+ emulator_base=emulators.UnityEmulatorBase,
61+ )
62+
63+ def stop_application(self):
64+ process_helpers.stop_job('unity8-dash')
tests/autopilot/unity8/process_helpers.py+89−20
@@ -36,6 +36,10 @@ from unity8.shell.emulators import main_window as main_window_emulator
3636logger = logging.getLogger(__name__)
3737
3838
39+class JobError(Exception):
40+ pass
41+
42+
3943class CannotAccessUnity(Exception):
4044 pass
4145
@@ -134,48 +138,113 @@ def restart_unity(*args):
134138 """
135139 status = _get_unity_status()
136140 if "start/" in status:
137− try:
138− output = subprocess.check_output(
139− ['/sbin/initctl', 'stop', 'unity8'])
140− logger.info(output)
141− except subprocess.CalledProcessError as e:
142− e.args += (
143− "Failed to stop running instance of unity8: %s" % e.output,
144− )
145− raise
141+ stop_job('unity8')
142+
143+ pid = start_job('unity8', *args)
144+ return _get_unity_proxy_object(pid)
146145
146+
147+def start_job(name, *args):
148+ """Start a job.
149+
150+ :param str name: The name of the job.
151+ :param args: The arguments to be used when starting the job.
152+ :return: The process id of the started job.
153+ :raises CalledProcessError: if the job failed to start.
154+
155+ """
156+ logger.info('Starting job {} with arguments {}.'.format(name, args))
157+ command = ['/sbin/initctl', 'start', name] + list(args)
147158 try:
148− command = ['/sbin/initctl', 'start', 'unity8'] + list(args)
149159 output = subprocess.check_output(
150160 command,
151161 stderr=subprocess.STDOUT,
152162 universal_newlines=True,
153163 )
154164 logger.info(output)
155− pid = _get_unity_pid()
165+ pid = get_job_pid(name)
156166 except subprocess.CalledProcessError as e:
157− e.args += ("Failed to start unity8: %s" % e.output,)
167+ e.args += ('Failed to start {}: {}.'.format(name, e.output),)
158168 raise
159169 else:
160− return _get_unity_proxy_object(pid)
170+ return pid
161171
162172
163−def _get_unity_status():
173+def get_job_pid(name):
174+ """Return the process id of a running job.
175+
176+ :param str name: The name of the job.
177+ :raises JobError: if the job is not running.
178+
179+ """
180+ status = get_job_status(name)
181+ if "start/" not in status:
182+ raise JobError('{} is not in the running state.'.format(name))
183+ return int(status.split()[-1])
184+
185+
186+def get_job_status(name):
187+ """Return the status of a job.
188+
189+ :param str name: The name of the job.
190+ :raises JobError: if it's not possible to get the status of the job.
191+
192+ """
164193 try:
165194 return subprocess.check_output([
166195 '/sbin/initctl',
167196 'status',
168− 'unity8'
197+ name
169198 ], universal_newlines=True)
199+ except subprocess.CalledProcessError as error:
200+ raise JobError(
201+ "Unable to get {}'s status: {}".format(name, error)
202+ )
203+
204+
205+def stop_job(name):
206+ """Stop a job.
207+
208+ :param str name: The name of the job.
209+ :raises CalledProcessError: if the job failed to stop.
210+
211+ """
212+ logger.info('Stoping job {}.'.format(name))
213+ command = ['/sbin/initctl', 'stop', name]
214+ try:
215+ output = subprocess.check_output(
216+ command,
217+ stderr=subprocess.STDOUT,
218+ universal_newlines=True,
219+ )
220+ logger.info(output)
170221 except subprocess.CalledProcessError as e:
171− raise CannotAccessUnity("Unable to get unity's status: %s" % str(e))
222+ e.args += ('Failed to stop {}: {}.'.format(name, e.output),)
223+ raise
224+
225+
226+def is_job_running(name):
227+ """Return True if the job is running. Otherwise, False.
228+
229+ :param str name: The name of the job.
230+ :raises JobError: if it's not possible to get the status of the job.
231+
232+ """
233+ return 'start/' in get_job_status(name)
234+
235+
236+def _get_unity_status():
237+ try:
238+ return get_job_status('unity8')
239+ except JobError as error:
240+ raise CannotAccessUnity(str(error))
172241
173242
174243def _get_unity_pid():
175− status = _get_unity_status()
176− if "start/" not in status:
177− raise CannotAccessUnity("Unity is not in the running state.")
178− return int(status.split()[-1])
244+ try:
245+ return get_job_pid('unity8')
246+ except JobError as error:
247+ raise CannotAccessUnity(str(error))
179248
180249
181250def _get_unity_proxy_object(pid):
tests/autopilot/unity8/shell/emulators/dash.py+21−8
@@ -31,6 +31,17 @@ from ubuntuuitoolkit import emulators as toolkit_emulators
3131logger = logging.getLogger(__name__)
3232
3333
34+class DashApp(object):
35+
36+ """Autopilot helper for the Dash app."""
37+
38+ def __init__(self, app_proxy):
39+ self.app_proxy = app_proxy
40+ self.main_view = self.app_proxy.select_single(
41+ toolkit_emulators.MainView)
42+ self.dash = self.main_view.select_single(Dash)
43+
44+
3445class Dash(emulators.UnityEmulatorBase):
3546 """An emulator that understands the Dash."""
3647
@@ -109,20 +120,22 @@ class Dash(emulators.UnityEmulatorBase):
109120 @autopilot_logging.log_action(logger.info)
110121 def _scroll_to_left_scope(self):
111122 original_index = self.dash_content_list.currentIndex
112− dashContent = self.select_single(objectName="dashContent")
113− start_x = dashContent.width / 3
114− stop_x = dashContent.width / 3 * 2
115− start_y = stop_y = dashContent.globalRect.y + 1
123+ dash_content = self.select_single(objectName="dashContent")
124+ x, y, width, height = dash_content.globalRect
125+ start_x = x + width / 3
126+ stop_x = x + width / 3 * 2
127+ start_y = stop_y = y + 1
116128 self.pointing_device.drag(start_x, start_y, stop_x, stop_y)
117129 self.dash_content_list.currentIndex.wait_for(original_index - 1)
118130
119131 @autopilot_logging.log_action(logger.info)
120132 def _scroll_to_right_scope(self):
121133 original_index = self.dash_content_list.currentIndex
122− dashContent = self.select_single(objectName="dashContent")
123− start_x = dashContent.width / 3 * 2
124− stop_x = dashContent.width / 3
125− start_y = stop_y = dashContent.globalRect.y + 1
134+ dash_content = self.select_single(objectName="dashContent")
135+ x, y, width, height = dash_content.globalRect
136+ start_x = x + width / 3 * 2
137+ stop_x = x + width / 3
138+ start_y = stop_y = y + 1
126139 self.pointing_device.drag(start_x, start_y, stop_x, stop_y)
127140 self.dash_content_list.currentIndex.wait_for(original_index + 1)
128141
tests/autopilot/unity8/shell/emulators/greeter.py+4−1
@@ -17,6 +17,8 @@
1717# along with this program. If not, see <http://www.gnu.org/licenses/>.
1818#
1919
20+import ubuntuuitoolkit
21+
2022from unity8.shell.emulators import UnityEmulatorBase
2123
2224
@@ -37,4 +39,5 @@ class Greeter(UnityEmulatorBase):
3739 self.created.wait_for(False)
3840
3941 def get_prompt(self):
40− return self.select_single("TextField", objectName="passwordInput")
42+ return self.select_single(
43+ ubuntuuitoolkit.TextField, objectName='passwordInput')
tests/autopilot/unity8/shell/emulators/main_window.py+34−20
@@ -25,7 +25,6 @@ from autopilot import input
2525from unity8.shell import emulators
2626from unity8.shell.emulators.greeter import Greeter
2727from unity8.shell.emulators.hud import Hud
28−from unity8.shell.emulators.dash import Dash
2928from unity8.shell.emulators.launcher import Launcher
3029
3130logger = logging.getLogger(__name__)
@@ -61,9 +60,6 @@ class QQuickView(emulators.UnityEmulatorBase):
6160 def get_hud_edge_drag_area(self):
6261 return self.select_single(objectName="hudDragArea")
6362
64− def get_dash(self):
65− return self.select_single(Dash)
66−
6763 def get_bottombar(self):
6864 return self.select_single("Bottombar")
6965
@@ -76,12 +72,6 @@ class QQuickView(emulators.UnityEmulatorBase):
7672 objectName="pinPadLoader"
7773 )
7874
79− def get_pinPadButton(self, buttonId):
80− return self.select_single(
81− "PinPadButton",
82− objectName="pinPadButton%i" % buttonId
83− )
84−
8575 def get_lockscreen(self):
8676 return self.select_single("Lockscreen")
8777
@@ -117,20 +107,44 @@ class QQuickView(emulators.UnityEmulatorBase):
117107 @autopilot_logging.log_action(logger.info)
118108 def show_dash_swiping(self):
119109 """Show the dash swiping from the left."""
120− width = self.width
121− height = self.height
122− start_x = 0
123− start_y = height // 2
124− end_x = width
125− end_y = start_y
110+ x, y, width, height = self._get_shell().globalRect
111+ start_x = x
112+ end_x = x + width
113+ start_y = end_y = y + height // 2
126114
127115 self.pointing_device.drag(start_x, start_y, end_x, end_y)
128− return self.get_dash()
116+
117+ def _get_shell(self):
118+ return self.select_single('Shell')
129119
130120 def get_current_focused_app_id(self):
131121 """Return the id of the focused application."""
132− return self.select_single('Shell').focusedApplicationId
122+ return self._get_shell().focusedApplicationId
133123
134124 @autopilot_logging.log_action(logger.info)
135− def search(self, query):
136− self.get_dash().enter_search_query(query)
125+ def enter_pin_code(self, code):
126+ """Enter code 'code' into the single-pin lightdm pincode entry screen.
127+
128+ :param code: must be a string of numeric characters.
129+ :raises: TypeError if code is not a string.
130+ :raises: ValueError if code contains non-numeric characters.
131+
132+ """
133+ if not isinstance(code, str):
134+ raise TypeError(
135+ "'code' parameter must be a string, not %r."
136+ % type(code)
137+ )
138+ for num in code:
139+ if not num.isdigit():
140+ raise ValueError(
141+ "'code' parameter contains non-numeric characters."
142+ )
143+ self.pointing_device.click_object(
144+ self._get_pinpad_button(int(num)))
145+
146+ def _get_pinpad_button(self, button_id):
147+ return self.select_single(
148+ 'PinPadButton',
149+ objectName='pinPadButton{}'.format(button_id)
150+ )
tests/autopilot/unity8/shell/tests/__init__.py+141−48
@@ -24,6 +24,7 @@ try:
2424except ImportError:
2525 Gio = None
2626
27+from autopilot import introspection
2728from autopilot.platform import model
2829from autopilot.testcase import AutopilotTestCase
2930from autopilot.matchers import Eventually
@@ -34,6 +35,10 @@ import os.path
3435import subprocess
3536import sys
3637from testtools.matchers import Equals
38+from ubuntuuitoolkit import (
39+ fixture_setup as toolkit_fixtures,
40+ ubuntu_scenarios
41+)
3742
3843from unity8 import (
3944 get_lib_path,
@@ -42,9 +47,15 @@ from unity8 import (
4247 get_default_extra_mock_libraries,
4348 get_data_dirs
4449)
45−from unity8.process_helpers import restart_unity_with_testability
46−from unity8.shell.emulators import main_window as main_window_emulator
47−from unity8.shell.emulators.dash import Dash
50+from unity8 import (
51+ fixture_setup,
52+ process_helpers
53+)
54+from unity8.shell import emulators
55+from unity8.shell.emulators import (
56+ dash as dash_helpers,
57+ main_window as main_window_emulator,
58+)
4859
4960
5061logger = logging.getLogger(__name__)
@@ -78,6 +89,26 @@ def _get_device_emulation_scenarios(devices='All'):
7889 return [native]
7990
8091
92+def is_unity7_running():
93+ """Return True if Unity7 is running. Otherwise, return False."""
94+ return (
95+ Gio is not None and
96+ UNITYSHELL_GSETTINGS_SCHEMA in
97+ Gio.Settings.list_relocatable_schemas()
98+ )
99+
100+
101+def get_qml_import_path_with_mock():
102+ """Return the QML2_IMPORT_PATH value with the mock path prepended."""
103+ qml_import_path = [get_mocks_library_path()]
104+ if os.getenv('QML2_IMPORT_PATH') is not None:
105+ qml_import_path.append(os.getenv('QML2_IMPORT_PATH'))
106+
107+ qml_import_path = ':'.join(qml_import_path)
108+ logger.info("New QML2 import path: %s", qml_import_path)
109+ return qml_import_path
110+
111+
81112class UnityTestCase(AutopilotTestCase):
82113
83114 """A test case base class for the Unity shell tests."""
@@ -118,23 +149,8 @@ class UnityTestCase(AutopilotTestCase):
118149
119150 def setUp(self):
120151 super(UnityTestCase, self).setUp()
121− if (Gio is not None and
122− UNITYSHELL_GSETTINGS_SCHEMA in
123− Gio.Settings.list_relocatable_schemas()):
124−
125− # Hide Unity launcher
126− self._unityshell_schema = Gio.Settings.new_with_path(
127− UNITYSHELL_GSETTINGS_SCHEMA,
128− UNITYSHELL_GSETTINGS_PATH,
129− )
130− self._launcher_hide_mode = self._unityshell_schema.get_int(
131− UNITYSHELL_LAUNCHER_KEY,
132− )
133− self._unityshell_schema.set_int(
134− UNITYSHELL_LAUNCHER_KEY,
135− UNITYSHELL_LAUNCHER_MODE,
136− )
137− self.addCleanup(self._reset_launcher)
152+ if is_unity7_running():
153+ self.useFixture(toolkit_fixtures.HideUnity7Launcher())
138154
139155 self._proxy = None
140156 self._lightdm_mock_type = None
@@ -151,13 +167,6 @@ class UnityTestCase(AutopilotTestCase):
151167 self.touch = Touch.create()
152168 self._setup_display_details()
153169
154− def _reset_launcher(self):
155− """Reset Unity launcher hide mode"""
156− self._unityshell_schema.set_int(
157− UNITYSHELL_LAUNCHER_KEY,
158− self._launcher_hide_mode,
159− )
160−
161170 def _setup_display_details(self):
162171 scale_divisor = self._determine_geometry()
163172 self._setup_grid_size(scale_divisor)
@@ -263,7 +272,9 @@ class UnityTestCase(AutopilotTestCase):
263272 self.patch_lightdm_mock()
264273
265274 if self._qml_mock_enabled:
266− self._setup_extra_mock_environment_patch()
275+ self._environment['QML2_IMPORT_PATH'] = (
276+ get_qml_import_path_with_mock()
277+ )
267278
268279 if self._data_dirs_mock_enabled:
269280 self._patch_data_dirs()
@@ -292,9 +303,14 @@ class UnityTestCase(AutopilotTestCase):
292303
293304 # Ensure that the dash is visible before we return:
294305 logger.debug("Unity started, waiting for it to be ready.")
295− self.assertUnityReady()
306+ self.wait_for_unity()
296307 logger.debug("Unity loaded and ready.")
297308
309+ if model() == 'Desktop':
310+ # On desktop, close the dash because it's opened in a separate
311+ # window and it gets in the way.
312+ process_helpers.stop_job('unity8-dash')
313+
298314 return app_proxy
299315
300316 def _launch_unity_with_upstart(self, binary_path, args):
@@ -308,7 +324,7 @@ class UnityTestCase(AutopilotTestCase):
308324
309325 self.addCleanup(self._cleanup_launching_upstart_unity)
310326
311− return restart_unity_with_testability(*all_args)
327+ return process_helpers.restart_unity_with_testability(*all_args)
312328
313329 def _cleanup_launching_upstart_unity(self):
314330 logger.info("Stopping unity")
@@ -353,15 +369,6 @@ class UnityTestCase(AutopilotTestCase):
353369 )
354370 return lightdm_mock_path
355371
356− def _setup_extra_mock_environment_patch(self):
357− qml_import_path = [get_mocks_library_path()]
358− if os.getenv('QML2_IMPORT_PATH') is not None:
359− qml_import_path.append(os.getenv('QML2_IMPORT_PATH'))
360−
361− qml_import_path = ':'.join(qml_import_path)
362− logger.info("New QML2 import path: %s", qml_import_path)
363− self._environment['QML2_IMPORT_PATH'] = qml_import_path
364−
365372 def _set_proxy(self, proxy):
366373 """Keep a copy of the proxy object, so we can use it to get common
367374 parts of the shell later on.
@@ -373,10 +380,80 @@ class UnityTestCase(AutopilotTestCase):
373380 def _clear_proxy(self):
374381 self._proxy = None
375382
376− def assertUnityReady(self):
377− dash = self.get_dash()
378− home_scope = dash.get_scope('clickscope')
383+ def wait_for_unity(self):
384+ greeter_content_loader = self.main_window.wait_select_single(
385+ objectName='greeterContentLoader')
386+ greeter_content_loader.progress.wait_for(1)
387+
388+ def get_dash(self):
389+ pid = process_helpers.get_job_pid('unity8-dash')
390+ dash_proxy = introspection.get_proxy_object_for_existing_process(
391+ pid=pid,
392+ emulator_base=emulators.UnityEmulatorBase,
393+ )
394+ dash_app = dash_helpers.DashApp(dash_proxy)
395+ return dash_app.dash
396+
397+ @property
398+ def main_window(self):
399+ return self._proxy.select_single(main_window_emulator.QQuickView)
379400
401+
402+class DashBaseTestCase(AutopilotTestCase):
403+
404+ scenarios = ubuntu_scenarios.get_device_simulation_scenarios()
405+ qml_mock_enabled = True
406+ environment = {}
407+
408+ def setUp(self):
409+ super(DashBaseTestCase, self).setUp()
410+
411+ if is_unity7_running():
412+ self.useFixture(toolkit_fixtures.HideUnity7Launcher())
413+
414+ if model() != 'Desktop':
415+ # On the phone, we need unity to be running and unlocked.
416+ self.addCleanup(process_helpers.stop_job, 'unity8')
417+ process_helpers.restart_unity_with_testability()
418+ process_helpers.unlock_unity()
419+
420+ self.ensure_dash_not_running()
421+
422+ if self.qml_mock_enabled:
423+ self.environment['QML2_IMPORT_PATH'] = (
424+ get_qml_import_path_with_mock()
425+ )
426+
427+ if self.should_simulate_device():
428+ # This sets the grid units, so it should be called before launching
429+ # the app.
430+ self.simulate_device()
431+
432+ binary_path = get_binary_path('unity8-dash')
433+ dash_proxy = self.launch_dash(binary_path, self.environment)
434+
435+ if self.should_simulate_device():
436+ # XXX Currently we have no way to launch the application with a
437+ # specific size, so we must resize it after it's launched.
438+ # --elopio - 2014-06-25
439+ self.resize_window()
440+
441+ self.dash_app = dash_helpers.DashApp(dash_proxy)
442+ self.dash = self.dash_app.dash
443+ self.wait_for_dash()
444+
445+ def ensure_dash_not_running(self):
446+ if process_helpers.is_job_running('unity8-dash'):
447+ process_helpers.stop_job('unity8-dash')
448+
449+ def launch_dash(self, binary_path, variables):
450+ launch_dash_app_fixture = fixture_setup.LaunchDashApp(
451+ binary_path, variables)
452+ self.useFixture(launch_dash_app_fixture)
453+ return launch_dash_app_fixture.application_proxy
454+
455+ def wait_for_dash(self):
456+ home_scope = self.dash.get_scope('clickscope')
380457 # FIXME! There is a huge timeout here for when we're doing CI on
381458 # VMs. See lp:1203715
382459 self.assertThat(
@@ -385,10 +462,26 @@ class UnityTestCase(AutopilotTestCase):
385462 )
386463 self.assertThat(home_scope.isCurrent, Eventually(Equals(True)))
387464
388− def get_dash(self):
389− dash = self._proxy.wait_select_single(Dash)
390− return dash
465+ def should_simulate_device(self):
466+ return (hasattr(self, 'app_width') and hasattr(self, 'app_height') and
467+ hasattr(self, 'grid_unit_px'))
391468
392− @property
393− def main_window(self):
394− return self._proxy.select_single(main_window_emulator.QQuickView)
469+ def simulate_device(self):
470+ simulate_device_fixture = self.useFixture(
471+ toolkit_fixtures.SimulateDevice(
472+ self.app_width, self.app_height, self.grid_unit_px))
473+ self.app_width = simulate_device_fixture.app_width
474+ self.app_height = simulate_device_fixture.app_height
475+
476+ def resize_window(self):
477+ application = self.process_manager.get_running_applications()[0]
478+ window = application.get_windows()[0]
479+ window.resize(self.app_width, self.app_height)
480+
481+ def get_window_size():
482+ _, _, window_width, window_height = window.geometry
483+ return window_width, window_height
484+
485+ self.assertThat(
486+ get_window_size,
487+ Eventually(Equals((self.app_width, self.app_height))))
tests/autopilot/unity8/shell/tests/test_emulators.py+7−18
@@ -47,24 +47,13 @@ class MainWindowTestCase(tests.UnityTestCase):
4747 unity_proxy = self.launch_unity()
4848 process_helpers.unlock_unity(unity_proxy)
4949
50− def test_search(self):
51− self.main_window.search('Test')
52− text_field = self.main_window.get_dash()._get_search_text_field()
53− self.assertEqual(text_field.text, 'Test')
54−
55−
56−class DashBaseTestCase(tests.UnityTestCase):
57−
58− scenarios = tests._get_device_emulation_scenarios()
5950
60− def setUp(self):
61− super(DashBaseTestCase, self).setUp()
62− unity_proxy = self.launch_unity()
63− process_helpers.unlock_unity(unity_proxy)
64− self.dash = self.main_window.get_dash()
51+class DashEmulatorTestCase(tests.DashBaseTestCase):
6552
66−
67−class DashEmulatorTestCase(DashBaseTestCase):
53+ def test_search(self):
54+ self.dash.enter_search_query('Test')
55+ text_field = self.dash._get_search_text_field()
56+ self.assertEqual(text_field.text, 'Test')
6857
6958 def test_open_unexisting_scope(self):
7059 scope_name = 'unexisting'
@@ -145,7 +134,7 @@ class DashEmulatorTestCase(DashBaseTestCase):
145134 self.assertIsInstance(scope, dash_emulators.GenericScopeView)
146135
147136
148−class GenericScopeViewEmulatorTestCase(DashBaseTestCase):
137+class GenericScopeViewEmulatorTestCase(tests.DashBaseTestCase):
149138
150139 def setUp(self):
151140 # Set up the fake scopes before launching unity.
@@ -159,7 +148,7 @@ class GenericScopeViewEmulatorTestCase(DashBaseTestCase):
159148 self.assertTrue(preview.isCurrent)
160149
161150
162−class DashAppsEmulatorTestCase(DashBaseTestCase):
151+class DashAppsEmulatorTestCase(tests.DashBaseTestCase):
163152
164153 available_applications = [
165154 'Title.2.0', 'Title.2.1', 'Title.2.2', 'Title.2.3', 'Title.2.4',
tests/autopilot/unity8/shell/tests/test_lock_screen.py+7−47
@@ -51,7 +51,7 @@ class TestLockscreen(UnityTestCase):
5151 if greeter.narrowMode:
5252 unlock_unity(unity_proxy)
5353 lockscreen = self._wait_for_lockscreen()
54− self._enter_pincode("1234")
54+ self.main_window.enter_pin_code("1234")
5555 self.assertThat(lockscreen.shown, Eventually(Equals(False)))
5656 else:
5757 self._enter_prompt_passphrase("1234")
@@ -81,7 +81,7 @@ class TestLockscreen(UnityTestCase):
8181 if greeter.narrowMode:
8282 unlock_unity(unity_proxy)
8383 lockscreen = self._wait_for_lockscreen()
84− self._enter_pincode("4321")
84+ self.main_window.enter_pin_code("4321")
8585 pinentryField = self.main_window.get_pinentryField()
8686 self.assertThat(pinentryField.text, Eventually(Equals("")))
8787 self.assertThat(lockscreen.shown, Eventually(Equals(True)))
@@ -118,28 +118,6 @@ class TestLockscreen(UnityTestCase):
118118 self.assertThat(lockscreen.shown, Eventually(Equals(True)))
119119 return lockscreen
120120
121− def _enter_pincode(self, code):
122− """Enter code 'code' into the single-pin lightdm pincode entry
123− screen.
124−
125− :param code: must be a string of numeric characters.
126− :raises: TypeError if code is not a string.
127− :raises: ValueError if code contains non-numeric characters.
128−
129− """
130−
131− if not isinstance(code, basestring):
132− raise TypeError(
133− "'code' parameter must be a string, not %r."
134− % type(code)
135− )
136− for num in code:
137− if not num.isdigit():
138− raise ValueError(
139− "'code' parameter contains non-numeric characters."
140− )
141− self.touch.tap_object(self.main_window.get_pinPadButton(int(num)))
142−
143121 def _enter_pin_passphrase(self, passphrase):
144122 """Enter the password specified in 'passphrase' into the password entry
145123 field of the pin lock screen.
@@ -148,18 +126,15 @@ class TestLockscreen(UnityTestCase):
148126 :raises: TypeError if passphrase is not a string.
149127
150128 """
151− if not isinstance(passphrase, basestring):
129+ if not isinstance(passphrase, str):
152130 raise TypeError(
153131 "'passphrase' parameter must be a string, not %r."
154132 % type(passphrase)
155133 )
156134
157− pinentryField = self.main_window.get_pinentryField()
158− self.touch.tap_object(pinentryField)
159− self.assertThat(pinentryField.activeFocus, Eventually(Equals(True)))
160− for character in passphrase:
161− self._type_character(character, pinentryField)
162− logger.debug("Typed passphrase: %s", pinentryField.text)
135+ pin_entry_field = self.main_window.get_pinentryField()
136+ pin_entry_field.write(passphrase)
137+ logger.debug("Typed passphrase: %s", pin_entry_field.text)
163138 self.keyboard.type("\n")
164139
165140 def _enter_prompt_passphrase(self, passphrase):
@@ -177,21 +152,6 @@ class TestLockscreen(UnityTestCase):
177152 )
178153
179154 prompt = self.main_window.get_greeter().get_prompt()
180− self.touch.tap_object(prompt)
181− self.assertThat(prompt.activeFocus, Eventually(Equals(True)))
182− for character in passphrase:
183− self._type_character(character, prompt)
155+ prompt.write(passphrase)
184156 logger.debug("Typed passphrase: %s", prompt.text)
185157 self.keyboard.type("\n")
186−
187− def _type_character(self, character, prompt, retries=5):
188− current_text = prompt.text
189− self.keyboard.type(character)
190− try:
191− self.assertThat(
192− prompt.text, Eventually(Equals(current_text + character)))
193− except AssertionError:
194− if retries > 0:
195− self._type_character(character, prompt, retries-1)
196− else:
197− raise
tests/autopilot/unity8/shell/tests/test_notifications.py+12−7
@@ -154,7 +154,7 @@ class InteractiveNotificationBase(NotificationsBase):
154154 'Notification', objectName='notification1')
155155 notification = get_notification()
156156
157− self.touch.tap_object(
157+ notification.pointing_device.click_object(
158158 notification.select_single(objectName="interactiveArea")
159159 )
160160
@@ -201,11 +201,14 @@ class InteractiveNotificationBase(NotificationsBase):
201201 'Notification', objectName='notification1')
202202 notification = get_notification()
203203 self._assert_notification(notification, summary, body, True, True, 1.0)
204− initial_height = notification.height
205− self.touch.tap_object(notification.select_single(objectName="combobutton_dropdown"))
206− self.assertThat(notification.select_single(objectName="button2").expanded, Eventually(Equals(True)))
204+ notification.pointing_device.click_object(
205+ notification.select_single(objectName="combobutton_dropdown"))
206+ self.assertThat(
207+ notification.select_single(objectName="button2").expanded,
208+ Eventually(Equals(True)))
207209 time.sleep(2)
208− self.touch.tap_object(notification.select_single(objectName="button4"))
210+ notification.pointing_device.click_object(
211+ notification.select_single(objectName="button4"))
209212 self.assert_notification_action_id_was_called("action_decline_4")
210213
211214 def test_modal_sd_without_greeter(self):
@@ -249,7 +252,8 @@ class InteractiveNotificationBase(NotificationsBase):
249252 notification = get_notification()
250253 self._assert_notification(
251254 notification, summary, body, True, False, 1.0)
252− self.touch.tap_object(notification.select_single(objectName="button0"))
255+ notification.pointing_device.click_object(
256+ notification.select_single(objectName="button0"))
253257 self.assert_notification_action_id_was_called("action_accept")
254258
255259 def test_modal_sd_with_greeter(self):
@@ -291,7 +295,8 @@ class InteractiveNotificationBase(NotificationsBase):
291295 notification = get_notification()
292296 self._assert_notification(
293297 notification, summary, body, True, False, 1.0)
294− self.touch.tap_object(notification.select_single(objectName="button0"))
298+ notification.pointing_device.click_object(
299+ notification.select_single(objectName="button0"))
295300 self.assert_notification_action_id_was_called("action_accept")
296301
297302 def _create_interactive_notification(
tests/autopilot/unity8/shell/tests/test_upstart.py+2−2
@@ -119,7 +119,7 @@ class UpstartIntegrationTests(UnityTestCase):
119119 self._set_proxy()
120120
121121 logger.debug("Unity started, waiting for it to be ready.")
122− self.assertUnityReady()
122+ self.wait_for_unity()
123123 logger.debug("Unity loaded and ready.")
124124
125125 def test_expect_sigstop(self):
@@ -137,5 +137,5 @@ class UpstartIntegrationTests(UnityTestCase):
137137
138138 logger.debug("Unity started, waiting for it to be ready.")
139139 self._set_proxy()
140− self.assertUnityReady()
140+ self.wait_for_unity()
141141 logger.debug("Unity loaded and ready.")