Merge lp:~canonical-platform-qa/unity8/dash-as-app-autopilot into lp:unity8

Proposed by Leo Arias
Status: Merged
Approved by: Michał Sawicz
Approved revision: 1128
Merged at revision: 1112
Proposed branch: lp:~canonical-platform-qa/unity8/dash-as-app-autopilot
Merge into: lp:unity8
Prerequisite: lp:~unity-team/unity8/dash-as-app
Diff against target: 918 lines (+390/-179)
12 files modified
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/-0)
tests/autopilot/unity8/process_helpers.py (+92/-23)
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 (+143/-50)
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)
To merge this branch: bzr merge lp:~canonical-platform-qa/unity8/dash-as-app-autopilot
Reviewer Review Type Date Requested Status
Michał Sawicz Approve
PS Jenkins bot (community) continuous-integration Needs Fixing
Review via email: mp+229123@code.launchpad.net

This proposal supersedes a proposal from 2014-07-30.

Commit message

Update the autopilot tests to work with the new dash app.

To post a comment you must log in.
Revision history for this message
Leo Arias (elopio) wrote : Posted in a previous version of this proposal

Not ready yet. Just proposing to start getting jenkins results earlier.

1120. By Leo Arias

Merged with trunk.

1121. By Leo Arias

Removed extra space.

1122. By Leo Arias

Removed tags.

1123. By Leo Arias

Merged with prerequisite.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Leo Arias (elopio) wrote :

\o/ Only one error on the autopilot tests, the one that exposes a bug.

Revision history for this message
Michał Sawicz (saviq) wrote :

Minor comments inline.

Thanks!

review: Needs Fixing
1124. By Leo Arias

Remove unused import.

1125. By Leo Arias

Fixed typo.

1126. By Leo Arias

Fixed typo.

1127. By Leo Arias

Fixed grammar erro.

1128. By Leo Arias

Only check for the start part of the status, as suggested by saviq.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Michał Sawicz (saviq) wrote :

Still good.

 * Did you perform an exploratory manual test run of the code change and any related functionality?
Yes.

 * Did CI run pass? If not, please explain why.
Known ap issue that's being fixed in the prerequisite, unrelated issues in qmltests.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'tests/autopilot/unity8/application_lifecycle/tests/test_application_lifecycle.py'
2--- tests/autopilot/unity8/application_lifecycle/tests/test_application_lifecycle.py 2014-06-11 15:36:51 +0000
3+++ tests/autopilot/unity8/application_lifecycle/tests/test_application_lifecycle.py 2014-08-04 16:55:24 +0000
4@@ -106,7 +106,7 @@
5 self.assert_current_focused_application(application_name)
6
7 self.main_window.show_dash_swiping()
8- self.assert_current_focused_application('')
9+ self.assert_current_focused_application('unity8-dash')
10
11 process_helpers.lock_unity()
12 greeter = self.main_window.get_greeter()
13
14=== modified file 'tests/autopilot/unity8/application_lifecycle/tests/test_url_dispatcher.py'
15--- tests/autopilot/unity8/application_lifecycle/tests/test_url_dispatcher.py 2014-06-11 15:36:51 +0000
16+++ tests/autopilot/unity8/application_lifecycle/tests/test_url_dispatcher.py 2014-08-04 16:55:24 +0000
17@@ -39,7 +39,8 @@
18 desktop_file_name = os.path.basename(desktop_file_path)
19 application_name, _ = os.path.splitext(desktop_file_name)
20
21- self.assertEqual('', self.main_window.get_current_focused_app_id())
22+ self.assertEqual(
23+ 'unity8-dash', self.main_window.get_current_focused_app_id())
24 self.addCleanup(os.system, 'pkill qmlscene')
25
26 subprocess.check_call(
27@@ -47,4 +48,4 @@
28 self.assert_current_focused_application(application_name)
29
30 self.main_window.show_dash_swiping()
31- self.assert_current_focused_application('')
32+ self.assert_current_focused_application('unity8-dash')
33
34=== added file 'tests/autopilot/unity8/fixture_setup.py'
35--- tests/autopilot/unity8/fixture_setup.py 1970-01-01 00:00:00 +0000
36+++ tests/autopilot/unity8/fixture_setup.py 2014-08-04 16:55:24 +0000
37@@ -0,0 +1,64 @@
38+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
39+#
40+# Unity Autopilot Test Suite
41+# Copyright (C) 2014 Canonical
42+#
43+# This program is free software: you can redistribute it and/or modify
44+# it under the terms of the GNU General Public License as published by
45+# the Free Software Foundation, either version 3 of the License, or
46+# (at your option) any later version.
47+#
48+# This program is distributed in the hope that it will be useful,
49+# but WITHOUT ANY WARRANTY; without even the implied warranty of
50+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
51+# GNU General Public License for more details.
52+#
53+# You should have received a copy of the GNU General Public License
54+# along with this program. If not, see <http://www.gnu.org/licenses/>.
55+#
56+
57+import fixtures
58+from autopilot import introspection
59+
60+from unity8 import process_helpers
61+from unity8.shell import emulators
62+
63+
64+class LaunchDashApp(fixtures.Fixture):
65+
66+ """Fixture to launch the Dash app."""
67+
68+ def __init__(self, binary_path, variables):
69+ """Initialize an instance.
70+
71+ :param str binary_path: The path to the Dash app binary.
72+ :param variables: The variables to use when launching the app.
73+ :type variables: A dictionary.
74+
75+ """
76+ super(LaunchDashApp, self).__init__()
77+ self.binary_path = binary_path
78+ self.variables = variables
79+
80+ def setUp(self):
81+ """Launch the dash app when the fixture is used."""
82+ super(LaunchDashApp, self).setUp()
83+ self.addCleanup(self.stop_application)
84+ self.application_proxy = self.launch_application()
85+
86+ def launch_application(self):
87+ binary_arg = 'BINARY={}'.format(self.binary_path)
88+ testability_arg = 'QT_LOAD_TESTABILITY={}'.format(1)
89+ env_args = [
90+ '{}={}'.format(key, value) for key, value in self.variables.items()
91+ ]
92+ all_args = [binary_arg, testability_arg] + env_args
93+
94+ pid = process_helpers.start_job('unity8-dash', *all_args)
95+ return introspection.get_proxy_object_for_existing_process(
96+ pid=pid,
97+ emulator_base=emulators.UnityEmulatorBase,
98+ )
99+
100+ def stop_application(self):
101+ process_helpers.stop_job('unity8-dash')
102
103=== modified file 'tests/autopilot/unity8/process_helpers.py'
104--- tests/autopilot/unity8/process_helpers.py 2014-06-27 13:13:04 +0000
105+++ tests/autopilot/unity8/process_helpers.py 2014-08-04 16:55:24 +0000
106@@ -36,6 +36,10 @@
107 logger = logging.getLogger(__name__)
108
109
110+class JobError(Exception):
111+ pass
112+
113+
114 class CannotAccessUnity(Exception):
115 pass
116
117@@ -134,48 +138,113 @@
118 """
119 status = _get_unity_status()
120 if "start/" in status:
121- try:
122- output = subprocess.check_output(
123- ['/sbin/initctl', 'stop', 'unity8'])
124- logger.info(output)
125- except subprocess.CalledProcessError as e:
126- e.args += (
127- "Failed to stop running instance of unity8: %s" % e.output,
128- )
129- raise
130-
131+ stop_job('unity8')
132+
133+ pid = start_job('unity8', *args)
134+ return _get_unity_proxy_object(pid)
135+
136+
137+def start_job(name, *args):
138+ """Start a job.
139+
140+ :param str name: The name of the job.
141+ :param args: The arguments to be used when starting the job.
142+ :return: The process id of the started job.
143+ :raises CalledProcessError: if the job failed to start.
144+
145+ """
146+ logger.info('Starting job {} with arguments {}.'.format(name, args))
147+ command = ['/sbin/initctl', 'start', name] + list(args)
148 try:
149- command = ['/sbin/initctl', 'start', 'unity8'] + list(args)
150 output = subprocess.check_output(
151 command,
152 stderr=subprocess.STDOUT,
153 universal_newlines=True,
154 )
155 logger.info(output)
156- pid = _get_unity_pid()
157+ pid = get_job_pid(name)
158 except subprocess.CalledProcessError as e:
159- e.args += ("Failed to start unity8: %s" % e.output,)
160+ e.args += ('Failed to start {}: {}.'.format(name, e.output),)
161 raise
162 else:
163- return _get_unity_proxy_object(pid)
164-
165-
166-def _get_unity_status():
167+ return pid
168+
169+
170+def get_job_pid(name):
171+ """Return the process id of a running job.
172+
173+ :param str name: The name of the job.
174+ :raises JobError: if the job is not running.
175+
176+ """
177+ status = get_job_status(name)
178+ if "start/" not in status:
179+ raise JobError('{} is not in the running state.'.format(name))
180+ return int(status.split()[-1])
181+
182+
183+def get_job_status(name):
184+ """Return the status of a job.
185+
186+ :param str name: The name of the job.
187+ :raises JobError: if it's not possible to get the status of the job.
188+
189+ """
190 try:
191 return subprocess.check_output([
192 '/sbin/initctl',
193 'status',
194- 'unity8'
195+ name
196 ], universal_newlines=True)
197+ except subprocess.CalledProcessError as error:
198+ raise JobError(
199+ "Unable to get {}'s status: {}".format(name, error)
200+ )
201+
202+
203+def stop_job(name):
204+ """Stop a job.
205+
206+ :param str name: The name of the job.
207+ :raises CalledProcessError: if the job failed to stop.
208+
209+ """
210+ logger.info('Stoping job {}.'.format(name))
211+ command = ['/sbin/initctl', 'stop', name]
212+ try:
213+ output = subprocess.check_output(
214+ command,
215+ stderr=subprocess.STDOUT,
216+ universal_newlines=True,
217+ )
218+ logger.info(output)
219 except subprocess.CalledProcessError as e:
220- raise CannotAccessUnity("Unable to get unity's status: %s" % str(e))
221+ e.args += ('Failed to stop {}: {}.'.format(name, e.output),)
222+ raise
223+
224+
225+def is_job_running(name):
226+ """Return True if the job is running. Otherwise, False.
227+
228+ :param str name: The name of the job.
229+ :raises JobError: if it's not possible to get the status of the job.
230+
231+ """
232+ return 'start/' in get_job_status(name)
233+
234+
235+def _get_unity_status():
236+ try:
237+ return get_job_status('unity8')
238+ except JobError as error:
239+ raise CannotAccessUnity(str(error))
240
241
242 def _get_unity_pid():
243- status = _get_unity_status()
244- if "start/" not in status:
245- raise CannotAccessUnity("Unity is not in the running state.")
246- return int(status.split()[-1])
247+ try:
248+ return get_job_pid('unity8')
249+ except JobError as error:
250+ raise CannotAccessUnity(str(error))
251
252
253 def _get_unity_proxy_object(pid):
254
255=== modified file 'tests/autopilot/unity8/shell/emulators/dash.py'
256--- tests/autopilot/unity8/shell/emulators/dash.py 2014-07-28 17:06:57 +0000
257+++ tests/autopilot/unity8/shell/emulators/dash.py 2014-08-04 16:55:24 +0000
258@@ -31,6 +31,17 @@
259 logger = logging.getLogger(__name__)
260
261
262+class DashApp(object):
263+
264+ """Autopilot helper for the Dash app."""
265+
266+ def __init__(self, app_proxy):
267+ self.app_proxy = app_proxy
268+ self.main_view = self.app_proxy.select_single(
269+ toolkit_emulators.MainView)
270+ self.dash = self.main_view.select_single(Dash)
271+
272+
273 class Dash(emulators.UnityEmulatorBase):
274 """An emulator that understands the Dash."""
275
276@@ -109,20 +120,22 @@
277 @autopilot_logging.log_action(logger.info)
278 def _scroll_to_left_scope(self):
279 original_index = self.dash_content_list.currentIndex
280- dashContent = self.select_single(objectName="dashContent")
281- start_x = dashContent.width / 3
282- stop_x = dashContent.width / 3 * 2
283- start_y = stop_y = dashContent.globalRect.y + 1
284+ dash_content = self.select_single(objectName="dashContent")
285+ x, y, width, height = dash_content.globalRect
286+ start_x = x + width / 3
287+ stop_x = x + width / 3 * 2
288+ start_y = stop_y = y + 1
289 self.pointing_device.drag(start_x, start_y, stop_x, stop_y)
290 self.dash_content_list.currentIndex.wait_for(original_index - 1)
291
292 @autopilot_logging.log_action(logger.info)
293 def _scroll_to_right_scope(self):
294 original_index = self.dash_content_list.currentIndex
295- dashContent = self.select_single(objectName="dashContent")
296- start_x = dashContent.width / 3 * 2
297- stop_x = dashContent.width / 3
298- start_y = stop_y = dashContent.globalRect.y + 1
299+ dash_content = self.select_single(objectName="dashContent")
300+ x, y, width, height = dash_content.globalRect
301+ start_x = x + width / 3 * 2
302+ stop_x = x + width / 3
303+ start_y = stop_y = y + 1
304 self.pointing_device.drag(start_x, start_y, stop_x, stop_y)
305 self.dash_content_list.currentIndex.wait_for(original_index + 1)
306
307
308=== modified file 'tests/autopilot/unity8/shell/emulators/greeter.py'
309--- tests/autopilot/unity8/shell/emulators/greeter.py 2014-01-09 15:53:05 +0000
310+++ tests/autopilot/unity8/shell/emulators/greeter.py 2014-08-04 16:55:24 +0000
311@@ -17,6 +17,8 @@
312 # along with this program. If not, see <http://www.gnu.org/licenses/>.
313 #
314
315+import ubuntuuitoolkit
316+
317 from unity8.shell.emulators import UnityEmulatorBase
318
319
320@@ -37,4 +39,5 @@
321 self.created.wait_for(False)
322
323 def get_prompt(self):
324- return self.select_single("TextField", objectName="passwordInput")
325+ return self.select_single(
326+ ubuntuuitoolkit.TextField, objectName='passwordInput')
327
328=== modified file 'tests/autopilot/unity8/shell/emulators/main_window.py'
329--- tests/autopilot/unity8/shell/emulators/main_window.py 2014-07-09 13:16:20 +0000
330+++ tests/autopilot/unity8/shell/emulators/main_window.py 2014-08-04 16:55:24 +0000
331@@ -25,7 +25,6 @@
332 from unity8.shell import emulators
333 from unity8.shell.emulators.greeter import Greeter
334 from unity8.shell.emulators.hud import Hud
335-from unity8.shell.emulators.dash import Dash
336 from unity8.shell.emulators.launcher import Launcher
337
338 logger = logging.getLogger(__name__)
339@@ -61,9 +60,6 @@
340 def get_hud_edge_drag_area(self):
341 return self.select_single(objectName="hudDragArea")
342
343- def get_dash(self):
344- return self.select_single(Dash)
345-
346 def get_bottombar(self):
347 return self.select_single("Bottombar")
348
349@@ -76,12 +72,6 @@
350 objectName="pinPadLoader"
351 )
352
353- def get_pinPadButton(self, buttonId):
354- return self.select_single(
355- "PinPadButton",
356- objectName="pinPadButton%i" % buttonId
357- )
358-
359 def get_lockscreen(self):
360 return self.select_single("Lockscreen")
361
362@@ -117,20 +107,44 @@
363 @autopilot_logging.log_action(logger.info)
364 def show_dash_swiping(self):
365 """Show the dash swiping from the left."""
366- width = self.width
367- height = self.height
368- start_x = 0
369- start_y = height // 2
370- end_x = width
371- end_y = start_y
372+ x, y, width, height = self._get_shell().globalRect
373+ start_x = x
374+ end_x = x + width
375+ start_y = end_y = y + height // 2
376
377 self.pointing_device.drag(start_x, start_y, end_x, end_y)
378- return self.get_dash()
379+
380+ def _get_shell(self):
381+ return self.select_single('Shell')
382
383 def get_current_focused_app_id(self):
384 """Return the id of the focused application."""
385- return self.select_single('Shell').focusedApplicationId
386+ return self._get_shell().focusedApplicationId
387
388 @autopilot_logging.log_action(logger.info)
389- def search(self, query):
390- self.get_dash().enter_search_query(query)
391+ def enter_pin_code(self, code):
392+ """Enter code 'code' into the single-pin lightdm pincode entry screen.
393+
394+ :param code: must be a string of numeric characters.
395+ :raises: TypeError if code is not a string.
396+ :raises: ValueError if code contains non-numeric characters.
397+
398+ """
399+ if not isinstance(code, str):
400+ raise TypeError(
401+ "'code' parameter must be a string, not %r."
402+ % type(code)
403+ )
404+ for num in code:
405+ if not num.isdigit():
406+ raise ValueError(
407+ "'code' parameter contains non-numeric characters."
408+ )
409+ self.pointing_device.click_object(
410+ self._get_pinpad_button(int(num)))
411+
412+ def _get_pinpad_button(self, button_id):
413+ return self.select_single(
414+ 'PinPadButton',
415+ objectName='pinPadButton{}'.format(button_id)
416+ )
417
418=== modified file 'tests/autopilot/unity8/shell/tests/__init__.py'
419--- tests/autopilot/unity8/shell/tests/__init__.py 2014-06-27 13:13:04 +0000
420+++ tests/autopilot/unity8/shell/tests/__init__.py 2014-08-04 16:55:24 +0000
421@@ -24,6 +24,7 @@
422 except ImportError:
423 Gio = None
424
425+from autopilot import introspection
426 from autopilot.platform import model
427 from autopilot.testcase import AutopilotTestCase
428 from autopilot.matchers import Eventually
429@@ -34,6 +35,10 @@
430 import subprocess
431 import sys
432 from testtools.matchers import Equals
433+from ubuntuuitoolkit import (
434+ fixture_setup as toolkit_fixtures,
435+ ubuntu_scenarios
436+)
437
438 from unity8 import (
439 get_lib_path,
440@@ -42,9 +47,15 @@
441 get_default_extra_mock_libraries,
442 get_data_dirs
443 )
444-from unity8.process_helpers import restart_unity_with_testability
445-from unity8.shell.emulators import main_window as main_window_emulator
446-from unity8.shell.emulators.dash import Dash
447+from unity8 import (
448+ fixture_setup,
449+ process_helpers
450+)
451+from unity8.shell import emulators
452+from unity8.shell.emulators import (
453+ dash as dash_helpers,
454+ main_window as main_window_emulator,
455+)
456
457
458 logger = logging.getLogger(__name__)
459@@ -78,6 +89,26 @@
460 return [native]
461
462
463+def is_unity7_running():
464+ """Return True if Unity7 is running. Otherwise, return False."""
465+ return (
466+ Gio is not None and
467+ UNITYSHELL_GSETTINGS_SCHEMA in
468+ Gio.Settings.list_relocatable_schemas()
469+ )
470+
471+
472+def get_qml_import_path_with_mock():
473+ """Return the QML2_IMPORT_PATH value with the mock path prepended."""
474+ qml_import_path = [get_mocks_library_path()]
475+ if os.getenv('QML2_IMPORT_PATH') is not None:
476+ qml_import_path.append(os.getenv('QML2_IMPORT_PATH'))
477+
478+ qml_import_path = ':'.join(qml_import_path)
479+ logger.info("New QML2 import path: %s", qml_import_path)
480+ return qml_import_path
481+
482+
483 class UnityTestCase(AutopilotTestCase):
484
485 """A test case base class for the Unity shell tests."""
486@@ -118,23 +149,8 @@
487
488 def setUp(self):
489 super(UnityTestCase, self).setUp()
490- if (Gio is not None and
491- UNITYSHELL_GSETTINGS_SCHEMA in
492- Gio.Settings.list_relocatable_schemas()):
493-
494- # Hide Unity launcher
495- self._unityshell_schema = Gio.Settings.new_with_path(
496- UNITYSHELL_GSETTINGS_SCHEMA,
497- UNITYSHELL_GSETTINGS_PATH,
498- )
499- self._launcher_hide_mode = self._unityshell_schema.get_int(
500- UNITYSHELL_LAUNCHER_KEY,
501- )
502- self._unityshell_schema.set_int(
503- UNITYSHELL_LAUNCHER_KEY,
504- UNITYSHELL_LAUNCHER_MODE,
505- )
506- self.addCleanup(self._reset_launcher)
507+ if is_unity7_running():
508+ self.useFixture(toolkit_fixtures.HideUnity7Launcher())
509
510 self._proxy = None
511 self._lightdm_mock_type = None
512@@ -151,13 +167,6 @@
513 self.touch = Touch.create()
514 self._setup_display_details()
515
516- def _reset_launcher(self):
517- """Reset Unity launcher hide mode"""
518- self._unityshell_schema.set_int(
519- UNITYSHELL_LAUNCHER_KEY,
520- self._launcher_hide_mode,
521- )
522-
523 def _setup_display_details(self):
524 scale_divisor = self._determine_geometry()
525 self._setup_grid_size(scale_divisor)
526@@ -263,7 +272,9 @@
527 self.patch_lightdm_mock()
528
529 if self._qml_mock_enabled:
530- self._setup_extra_mock_environment_patch()
531+ self._environment['QML2_IMPORT_PATH'] = (
532+ get_qml_import_path_with_mock()
533+ )
534
535 if self._data_dirs_mock_enabled:
536 self._patch_data_dirs()
537@@ -292,9 +303,14 @@
538
539 # Ensure that the dash is visible before we return:
540 logger.debug("Unity started, waiting for it to be ready.")
541- self.assertUnityReady()
542+ self.wait_for_unity()
543 logger.debug("Unity loaded and ready.")
544
545+ if model() == 'Desktop':
546+ # On desktop, close the dash because it's opened in a separate
547+ # window and it gets in the way.
548+ process_helpers.stop_job('unity8-dash')
549+
550 return app_proxy
551
552 def _launch_unity_with_upstart(self, binary_path, args):
553@@ -308,7 +324,7 @@
554
555 self.addCleanup(self._cleanup_launching_upstart_unity)
556
557- return restart_unity_with_testability(*all_args)
558+ return process_helpers.restart_unity_with_testability(*all_args)
559
560 def _cleanup_launching_upstart_unity(self):
561 logger.info("Stopping unity")
562@@ -353,15 +369,6 @@
563 )
564 return lightdm_mock_path
565
566- def _setup_extra_mock_environment_patch(self):
567- qml_import_path = [get_mocks_library_path()]
568- if os.getenv('QML2_IMPORT_PATH') is not None:
569- qml_import_path.append(os.getenv('QML2_IMPORT_PATH'))
570-
571- qml_import_path = ':'.join(qml_import_path)
572- logger.info("New QML2 import path: %s", qml_import_path)
573- self._environment['QML2_IMPORT_PATH'] = qml_import_path
574-
575 def _set_proxy(self, proxy):
576 """Keep a copy of the proxy object, so we can use it to get common
577 parts of the shell later on.
578@@ -373,10 +380,80 @@
579 def _clear_proxy(self):
580 self._proxy = None
581
582- def assertUnityReady(self):
583- dash = self.get_dash()
584- home_scope = dash.get_scope('clickscope')
585-
586+ def wait_for_unity(self):
587+ greeter_content_loader = self.main_window.wait_select_single(
588+ objectName='greeterContentLoader')
589+ greeter_content_loader.progress.wait_for(1)
590+
591+ def get_dash(self):
592+ pid = process_helpers.get_job_pid('unity8-dash')
593+ dash_proxy = introspection.get_proxy_object_for_existing_process(
594+ pid=pid,
595+ emulator_base=emulators.UnityEmulatorBase,
596+ )
597+ dash_app = dash_helpers.DashApp(dash_proxy)
598+ return dash_app.dash
599+
600+ @property
601+ def main_window(self):
602+ return self._proxy.select_single(main_window_emulator.QQuickView)
603+
604+
605+class DashBaseTestCase(AutopilotTestCase):
606+
607+ scenarios = ubuntu_scenarios.get_device_simulation_scenarios()
608+ qml_mock_enabled = True
609+ environment = {}
610+
611+ def setUp(self):
612+ super(DashBaseTestCase, self).setUp()
613+
614+ if is_unity7_running():
615+ self.useFixture(toolkit_fixtures.HideUnity7Launcher())
616+
617+ if model() != 'Desktop':
618+ # On the phone, we need unity to be running and unlocked.
619+ self.addCleanup(process_helpers.stop_job, 'unity8')
620+ process_helpers.restart_unity_with_testability()
621+ process_helpers.unlock_unity()
622+
623+ self.ensure_dash_not_running()
624+
625+ if self.qml_mock_enabled:
626+ self.environment['QML2_IMPORT_PATH'] = (
627+ get_qml_import_path_with_mock()
628+ )
629+
630+ if self.should_simulate_device():
631+ # This sets the grid units, so it should be called before launching
632+ # the app.
633+ self.simulate_device()
634+
635+ binary_path = get_binary_path('unity8-dash')
636+ dash_proxy = self.launch_dash(binary_path, self.environment)
637+
638+ if self.should_simulate_device():
639+ # XXX Currently we have no way to launch the application with a
640+ # specific size, so we must resize it after it's launched.
641+ # --elopio - 2014-06-25
642+ self.resize_window()
643+
644+ self.dash_app = dash_helpers.DashApp(dash_proxy)
645+ self.dash = self.dash_app.dash
646+ self.wait_for_dash()
647+
648+ def ensure_dash_not_running(self):
649+ if process_helpers.is_job_running('unity8-dash'):
650+ process_helpers.stop_job('unity8-dash')
651+
652+ def launch_dash(self, binary_path, variables):
653+ launch_dash_app_fixture = fixture_setup.LaunchDashApp(
654+ binary_path, variables)
655+ self.useFixture(launch_dash_app_fixture)
656+ return launch_dash_app_fixture.application_proxy
657+
658+ def wait_for_dash(self):
659+ home_scope = self.dash.get_scope('clickscope')
660 # FIXME! There is a huge timeout here for when we're doing CI on
661 # VMs. See lp:1203715
662 self.assertThat(
663@@ -385,10 +462,26 @@
664 )
665 self.assertThat(home_scope.isCurrent, Eventually(Equals(True)))
666
667- def get_dash(self):
668- dash = self._proxy.wait_select_single(Dash)
669- return dash
670-
671- @property
672- def main_window(self):
673- return self._proxy.select_single(main_window_emulator.QQuickView)
674+ def should_simulate_device(self):
675+ return (hasattr(self, 'app_width') and hasattr(self, 'app_height') and
676+ hasattr(self, 'grid_unit_px'))
677+
678+ def simulate_device(self):
679+ simulate_device_fixture = self.useFixture(
680+ toolkit_fixtures.SimulateDevice(
681+ self.app_width, self.app_height, self.grid_unit_px))
682+ self.app_width = simulate_device_fixture.app_width
683+ self.app_height = simulate_device_fixture.app_height
684+
685+ def resize_window(self):
686+ application = self.process_manager.get_running_applications()[0]
687+ window = application.get_windows()[0]
688+ window.resize(self.app_width, self.app_height)
689+
690+ def get_window_size():
691+ _, _, window_width, window_height = window.geometry
692+ return window_width, window_height
693+
694+ self.assertThat(
695+ get_window_size,
696+ Eventually(Equals((self.app_width, self.app_height))))
697
698=== modified file 'tests/autopilot/unity8/shell/tests/test_emulators.py'
699--- tests/autopilot/unity8/shell/tests/test_emulators.py 2014-07-25 11:49:28 +0000
700+++ tests/autopilot/unity8/shell/tests/test_emulators.py 2014-08-04 16:55:24 +0000
701@@ -47,25 +47,14 @@
702 unity_proxy = self.launch_unity()
703 process_helpers.unlock_unity(unity_proxy)
704
705+
706+class DashEmulatorTestCase(tests.DashBaseTestCase):
707+
708 def test_search(self):
709- self.main_window.search('Test')
710- text_field = self.main_window.get_dash()._get_search_text_field()
711+ self.dash.enter_search_query('Test')
712+ text_field = self.dash._get_search_text_field()
713 self.assertEqual(text_field.text, 'Test')
714
715-
716-class DashBaseTestCase(tests.UnityTestCase):
717-
718- scenarios = tests._get_device_emulation_scenarios()
719-
720- def setUp(self):
721- super(DashBaseTestCase, self).setUp()
722- unity_proxy = self.launch_unity()
723- process_helpers.unlock_unity(unity_proxy)
724- self.dash = self.main_window.get_dash()
725-
726-
727-class DashEmulatorTestCase(DashBaseTestCase):
728-
729 def test_open_unexisting_scope(self):
730 scope_name = 'unexisting'
731 with mock.patch.object(self.dash, 'pointing_device') as mock_pointer:
732@@ -145,7 +134,7 @@
733 self.assertIsInstance(scope, dash_emulators.GenericScopeView)
734
735
736-class GenericScopeViewEmulatorTestCase(DashBaseTestCase):
737+class GenericScopeViewEmulatorTestCase(tests.DashBaseTestCase):
738
739 def setUp(self):
740 # Set up the fake scopes before launching unity.
741@@ -159,7 +148,7 @@
742 self.assertTrue(preview.isCurrent)
743
744
745-class DashAppsEmulatorTestCase(DashBaseTestCase):
746+class DashAppsEmulatorTestCase(tests.DashBaseTestCase):
747
748 available_applications = [
749 'Title.2.0', 'Title.2.1', 'Title.2.2', 'Title.2.3', 'Title.2.4',
750
751=== modified file 'tests/autopilot/unity8/shell/tests/test_lock_screen.py'
752--- tests/autopilot/unity8/shell/tests/test_lock_screen.py 2014-06-18 01:52:15 +0000
753+++ tests/autopilot/unity8/shell/tests/test_lock_screen.py 2014-08-04 16:55:24 +0000
754@@ -51,7 +51,7 @@
755 if greeter.narrowMode:
756 unlock_unity(unity_proxy)
757 lockscreen = self._wait_for_lockscreen()
758- self._enter_pincode("1234")
759+ self.main_window.enter_pin_code("1234")
760 self.assertThat(lockscreen.shown, Eventually(Equals(False)))
761 else:
762 self._enter_prompt_passphrase("1234")
763@@ -81,7 +81,7 @@
764 if greeter.narrowMode:
765 unlock_unity(unity_proxy)
766 lockscreen = self._wait_for_lockscreen()
767- self._enter_pincode("4321")
768+ self.main_window.enter_pin_code("4321")
769 pinentryField = self.main_window.get_pinentryField()
770 self.assertThat(pinentryField.text, Eventually(Equals("")))
771 self.assertThat(lockscreen.shown, Eventually(Equals(True)))
772@@ -118,28 +118,6 @@
773 self.assertThat(lockscreen.shown, Eventually(Equals(True)))
774 return lockscreen
775
776- def _enter_pincode(self, code):
777- """Enter code 'code' into the single-pin lightdm pincode entry
778- screen.
779-
780- :param code: must be a string of numeric characters.
781- :raises: TypeError if code is not a string.
782- :raises: ValueError if code contains non-numeric characters.
783-
784- """
785-
786- if not isinstance(code, basestring):
787- raise TypeError(
788- "'code' parameter must be a string, not %r."
789- % type(code)
790- )
791- for num in code:
792- if not num.isdigit():
793- raise ValueError(
794- "'code' parameter contains non-numeric characters."
795- )
796- self.touch.tap_object(self.main_window.get_pinPadButton(int(num)))
797-
798 def _enter_pin_passphrase(self, passphrase):
799 """Enter the password specified in 'passphrase' into the password entry
800 field of the pin lock screen.
801@@ -148,18 +126,15 @@
802 :raises: TypeError if passphrase is not a string.
803
804 """
805- if not isinstance(passphrase, basestring):
806+ if not isinstance(passphrase, str):
807 raise TypeError(
808 "'passphrase' parameter must be a string, not %r."
809 % type(passphrase)
810 )
811
812- pinentryField = self.main_window.get_pinentryField()
813- self.touch.tap_object(pinentryField)
814- self.assertThat(pinentryField.activeFocus, Eventually(Equals(True)))
815- for character in passphrase:
816- self._type_character(character, pinentryField)
817- logger.debug("Typed passphrase: %s", pinentryField.text)
818+ pin_entry_field = self.main_window.get_pinentryField()
819+ pin_entry_field.write(passphrase)
820+ logger.debug("Typed passphrase: %s", pin_entry_field.text)
821 self.keyboard.type("\n")
822
823 def _enter_prompt_passphrase(self, passphrase):
824@@ -177,21 +152,6 @@
825 )
826
827 prompt = self.main_window.get_greeter().get_prompt()
828- self.touch.tap_object(prompt)
829- self.assertThat(prompt.activeFocus, Eventually(Equals(True)))
830- for character in passphrase:
831- self._type_character(character, prompt)
832+ prompt.write(passphrase)
833 logger.debug("Typed passphrase: %s", prompt.text)
834 self.keyboard.type("\n")
835-
836- def _type_character(self, character, prompt, retries=5):
837- current_text = prompt.text
838- self.keyboard.type(character)
839- try:
840- self.assertThat(
841- prompt.text, Eventually(Equals(current_text + character)))
842- except AssertionError:
843- if retries > 0:
844- self._type_character(character, prompt, retries-1)
845- else:
846- raise
847
848=== modified file 'tests/autopilot/unity8/shell/tests/test_notifications.py'
849--- tests/autopilot/unity8/shell/tests/test_notifications.py 2014-07-18 15:13:35 +0000
850+++ tests/autopilot/unity8/shell/tests/test_notifications.py 2014-08-04 16:55:24 +0000
851@@ -154,7 +154,7 @@
852 'Notification', objectName='notification1')
853 notification = get_notification()
854
855- self.touch.tap_object(
856+ notification.pointing_device.click_object(
857 notification.select_single(objectName="interactiveArea")
858 )
859
860@@ -201,11 +201,14 @@
861 'Notification', objectName='notification1')
862 notification = get_notification()
863 self._assert_notification(notification, summary, body, True, True, 1.0)
864- initial_height = notification.height
865- self.touch.tap_object(notification.select_single(objectName="combobutton_dropdown"))
866- self.assertThat(notification.select_single(objectName="button2").expanded, Eventually(Equals(True)))
867+ notification.pointing_device.click_object(
868+ notification.select_single(objectName="combobutton_dropdown"))
869+ self.assertThat(
870+ notification.select_single(objectName="button2").expanded,
871+ Eventually(Equals(True)))
872 time.sleep(2)
873- self.touch.tap_object(notification.select_single(objectName="button4"))
874+ notification.pointing_device.click_object(
875+ notification.select_single(objectName="button4"))
876 self.assert_notification_action_id_was_called("action_decline_4")
877
878 def test_modal_sd_without_greeter(self):
879@@ -249,7 +252,8 @@
880 notification = get_notification()
881 self._assert_notification(
882 notification, summary, body, True, False, 1.0)
883- self.touch.tap_object(notification.select_single(objectName="button0"))
884+ notification.pointing_device.click_object(
885+ notification.select_single(objectName="button0"))
886 self.assert_notification_action_id_was_called("action_accept")
887
888 def test_modal_sd_with_greeter(self):
889@@ -291,7 +295,8 @@
890 notification = get_notification()
891 self._assert_notification(
892 notification, summary, body, True, False, 1.0)
893- self.touch.tap_object(notification.select_single(objectName="button0"))
894+ notification.pointing_device.click_object(
895+ notification.select_single(objectName="button0"))
896 self.assert_notification_action_id_was_called("action_accept")
897
898 def _create_interactive_notification(
899
900=== modified file 'tests/autopilot/unity8/shell/tests/test_upstart.py'
901--- tests/autopilot/unity8/shell/tests/test_upstart.py 2014-07-31 10:11:27 +0000
902+++ tests/autopilot/unity8/shell/tests/test_upstart.py 2014-08-04 16:55:24 +0000
903@@ -119,7 +119,7 @@
904 self._set_proxy()
905
906 logger.debug("Unity started, waiting for it to be ready.")
907- self.assertUnityReady()
908+ self.wait_for_unity()
909 logger.debug("Unity loaded and ready.")
910
911 def test_expect_sigstop(self):
912@@ -137,5 +137,5 @@
913
914 logger.debug("Unity started, waiting for it to be ready.")
915 self._set_proxy()
916- self.assertUnityReady()
917+ self.wait_for_unity()
918 logger.debug("Unity loaded and ready.")

Subscribers

People subscribed via source and target branches