@@ -24,6 +24,7 @@ try:
24except ImportError:
24except ImportError:
25 Gio = None
25 Gio = None
27+from autopilot import introspection
27from autopilot.platform import model
28from autopilot.platform import model
28from autopilot.testcase import AutopilotTestCase
29from autopilot.testcase import AutopilotTestCase
29from autopilot.matchers import Eventually
30from autopilot.matchers import Eventually
@@ -34,6 +35,10 @@ import os.path
34import subprocess
35import subprocess
36from testtools.matchers import Equals
37from testtools.matchers import Equals
38+from ubuntuuitoolkit import (
39+ fixture_setup as toolkit_fixtures,
38from unity8 import (
43from unity8 import (
39 get_lib_path,
44 get_lib_path,
@@ -42,9 +47,15 @@ from unity8 import (
42 get_default_extra_mock_libraries,
47 get_default_extra_mock_libraries,
43 get_data_dirs
48 get_data_dirs
45−from unity8.process_helpers import restart_unity_with_testability
50+from unity8 import (
54+from unity8.shell import emulators
55+from unity8.shell.emulators import (
56+ dash as dash_helpers,
46−from unity8.shell.emulators import main_window as main_window_emulator
57+ main_window as main_window_emulator,
47−from unity8.shell.emulators.dash import Dash
58+)
50logger = logging.getLogger(__name__)
61logger = logging.getLogger(__name__)
@@ -78,6 +89,26 @@ def _get_device_emulation_scenarios(devices='All'):
78 return [native]
89 return [native]
92+def is_unity7_running():
93+ """Return True if Unity7 is running. Otherwise, return False."""
96+ UNITYSHELL_GSETTINGS_SCHEMA in
97+ Gio.Settings.list_relocatable_schemas()
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'))
107+ qml_import_path = ':'.join(qml_import_path)
108+ logger.info("New QML2 import path: %s", qml_import_path)
109+ return qml_import_path
81class UnityTestCase(AutopilotTestCase):
112class UnityTestCase(AutopilotTestCase):
83 """A test case base class for the Unity shell tests."""
114 """A test case base class for the Unity shell tests."""
@@ -118,23 +149,8 @@ class UnityTestCase(AutopilotTestCase):
119 def setUp(self):
150 def setUp(self):
120 super(UnityTestCase, self).setUp()
151 super(UnityTestCase, self).setUp()
121− if (Gio is not None and
152+ if is_unity7_running():
122− UNITYSHELL_GSETTINGS_SCHEMA in
153+ self.useFixture(toolkit_fixtures.HideUnity7Launcher())
123− Gio.Settings.list_relocatable_schemas()):
125− # Hide Unity launcher
126− self._unityshell_schema = Gio.Settings.new_with_path(
127− UNITYSHELL_GSETTINGS_SCHEMA,
128− UNITYSHELL_GSETTINGS_PATH,
130− self._launcher_hide_mode = self._unityshell_schema.get_int(
131− UNITYSHELL_LAUNCHER_KEY,
133− self._unityshell_schema.set_int(
134− UNITYSHELL_LAUNCHER_KEY,
135− UNITYSHELL_LAUNCHER_MODE,
137− self.addCleanup(self._reset_launcher)
139 self._proxy = None
155 self._proxy = None
140 self._lightdm_mock_type = None
156 self._lightdm_mock_type = None
@@ -151,13 +167,6 @@ class UnityTestCase(AutopilotTestCase):
151 self.touch = Touch.create()
167 self.touch = Touch.create()
152 self._setup_display_details()
168 self._setup_display_details()
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,
161 def _setup_display_details(self):
170 def _setup_display_details(self):
162 scale_divisor = self._determine_geometry()
171 scale_divisor = self._determine_geometry()
163 self._setup_grid_size(scale_divisor)
172 self._setup_grid_size(scale_divisor)
@@ -263,7 +272,9 @@ class UnityTestCase(AutopilotTestCase):
263 self.patch_lightdm_mock()
272 self.patch_lightdm_mock()
265 if self._qml_mock_enabled:
274 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()
268 if self._data_dirs_mock_enabled:
279 if self._data_dirs_mock_enabled:
269 self._patch_data_dirs()
280 self._patch_data_dirs()
@@ -292,9 +303,14 @@ class UnityTestCase(AutopilotTestCase):
293 # Ensure that the dash is visible before we return:
304 # Ensure that the dash is visible before we return:
294 logger.debug("Unity started, waiting for it to be ready.")
305 logger.debug("Unity started, waiting for it to be ready.")
295− self.assertUnityReady()
306+ self.wait_for_unity()
296 logger.debug("Unity loaded and ready.")
307 logger.debug("Unity loaded and ready.")
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')
298 return app_proxy
314 return app_proxy
300 def _launch_unity_with_upstart(self, binary_path, args):
316 def _launch_unity_with_upstart(self, binary_path, args):
@@ -308,7 +324,7 @@ class UnityTestCase(AutopilotTestCase):
309 self.addCleanup(self._cleanup_launching_upstart_unity)
325 self.addCleanup(self._cleanup_launching_upstart_unity)
311− return restart_unity_with_testability(*all_args)
327+ return process_helpers.restart_unity_with_testability(*all_args)
313 def _cleanup_launching_upstart_unity(self):
329 def _cleanup_launching_upstart_unity(self):
314 logger.info("Stopping unity")
330 logger.info("Stopping unity")
@@ -353,15 +369,6 @@ class UnityTestCase(AutopilotTestCase):
354 return lightdm_mock_path
370 return lightdm_mock_path
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'))
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
365 def _set_proxy(self, proxy):
372 def _set_proxy(self, proxy):
366 """Keep a copy of the proxy object, so we can use it to get common
373 """Keep a copy of the proxy object, so we can use it to get common
367 parts of the shell later on.
374 parts of the shell later on.
@@ -373,10 +380,80 @@ class UnityTestCase(AutopilotTestCase):
373 def _clear_proxy(self):
380 def _clear_proxy(self):
374 self._proxy = None
381 self._proxy = None
376− def assertUnityReady(self):
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)
377− dash = self.get_dash()
388+ def get_dash(self):
378− home_scope = dash.get_scope('clickscope')
389+ pid = process_helpers.get_job_pid('unity8-dash')
390+ dash_proxy = introspection.get_proxy_object_for_existing_process(
392+ emulator_base=emulators.UnityEmulatorBase,
394+ dash_app = dash_helpers.DashApp(dash_proxy)
395+ return dash_app.dash
398+ def main_window(self):
399+ return self._proxy.select_single(main_window_emulator.QQuickView)
402+class DashBaseTestCase(AutopilotTestCase):
404+ scenarios = ubuntu_scenarios.get_device_simulation_scenarios()
405+ qml_mock_enabled = True
409+ super(DashBaseTestCase, self).setUp()
411+ if is_unity7_running():
412+ self.useFixture(toolkit_fixtures.HideUnity7Launcher())
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()
420+ self.ensure_dash_not_running()
422+ if self.qml_mock_enabled:
423+ self.environment['QML2_IMPORT_PATH'] = (
424+ get_qml_import_path_with_mock()
427+ if self.should_simulate_device():
428+ # This sets the grid units, so it should be called before launching
430+ self.simulate_device()
432+ binary_path = get_binary_path('unity8-dash')
433+ dash_proxy = self.launch_dash(binary_path, self.environment)
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()
441+ self.dash_app = dash_helpers.DashApp(dash_proxy)
442+ self.dash = self.dash_app.dash
443+ self.wait_for_dash()
445+ def ensure_dash_not_running(self):
446+ if process_helpers.is_job_running('unity8-dash'):
447+ process_helpers.stop_job('unity8-dash')
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
455+ def wait_for_dash(self):
456+ home_scope = self.dash.get_scope('clickscope')
380 # FIXME! There is a huge timeout here for when we're doing CI on
457 # FIXME! There is a huge timeout here for when we're doing CI on
381 # VMs. See lp:1203715
458 # VMs. See lp:1203715
382 self.assertThat(
459 self.assertThat(
@@ -385,10 +462,26 @@ class UnityTestCase(AutopilotTestCase):
386 self.assertThat(home_scope.isCurrent, Eventually(Equals(True)))
463 self.assertThat(home_scope.isCurrent, Eventually(Equals(True)))
388− def get_dash(self):
465+ def should_simulate_device(self):
389− dash = self._proxy.wait_select_single(Dash)
466+ return (hasattr(self, 'app_width') and hasattr(self, 'app_height') and
390− return dash
467+ hasattr(self, 'grid_unit_px'))
392− @property
469+ def simulate_device(self):
393− def main_window(self):
470+ simulate_device_fixture = self.useFixture(
394− return self._proxy.select_single(main_window_emulator.QQuickView)
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
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)
481+ def get_window_size():
482+ _, _, window_width, window_height = window.geometry
483+ return window_width, window_height
487+ Eventually(Equals((self.app_width, self.app_height))))