Merge lp:~canonical-platform-qa/ubuntu-system-tests/move_unity_helpers into lp:ubuntu-system-tests

Proposed by Sergio Cazzolato
Status: Work in progress
Proposed branch: lp:~canonical-platform-qa/ubuntu-system-tests/move_unity_helpers
Merge into: lp:ubuntu-system-tests
Diff against target: 2582 lines (+1800/-260)
29 files modified
debian/control (+1/-3)
debian/tests/control (+0/-1)
ubuntu_system_tests/helpers/indicators/message.py (+3/-4)
ubuntu_system_tests/helpers/indicators/utils.py (+1/-2)
ubuntu_system_tests/helpers/mediascanner.py (+6/-6)
ubuntu_system_tests/helpers/processes.py (+83/-2)
ubuntu_system_tests/helpers/scopes/apps/_preview.py (+1/-1)
ubuntu_system_tests/helpers/scopes/base.py (+2/-2)
ubuntu_system_tests/helpers/scopes/music/_preview.py (+3/-3)
ubuntu_system_tests/helpers/sensors.py (+3/-2)
ubuntu_system_tests/helpers/ubuntuuitoolkit/slider.py (+1/-1)
ubuntu_system_tests/helpers/unity8/__init__.py (+20/-0)
ubuntu_system_tests/helpers/unity8/dash.py (+247/-26)
ubuntu_system_tests/helpers/unity8/fixture_setup.py (+307/-2)
ubuntu_system_tests/helpers/unity8/greeter.py (+59/-0)
ubuntu_system_tests/helpers/unity8/indicators.py (+179/-0)
ubuntu_system_tests/helpers/unity8/launcher.py (+66/-0)
ubuntu_system_tests/helpers/unity8/phone_stage.py (+5/-5)
ubuntu_system_tests/helpers/unity8/sensors.py (+83/-0)
ubuntu_system_tests/helpers/unity8/shell.py (+0/-169)
ubuntu_system_tests/helpers/unity8/shell/__init__.py (+31/-0)
ubuntu_system_tests/helpers/unity8/shell/_cpo.py (+319/-0)
ubuntu_system_tests/helpers/unity8/shell/fixture_setup.py (+90/-0)
ubuntu_system_tests/helpers/unity8/shell/utils.py (+82/-0)
ubuntu_system_tests/helpers/unity8/utils.py (+191/-8)
ubuntu_system_tests/selftests/test_tests_to_run.py (+1/-1)
ubuntu_system_tests/tests/base.py (+11/-13)
ubuntu_system_tests/tests/test_tutorial.py (+1/-5)
ubuntu_system_tests/tests/test_with_dialer.py (+4/-4)
To merge this branch: bzr merge lp:~canonical-platform-qa/ubuntu-system-tests/move_unity_helpers
Reviewer Review Type Date Requested Status
platform-qa-bot continuous-integration Needs Fixing
Santiago Baldassin (community) Needs Fixing
Richard Huddie (community) Needs Fixing
prod-platform-qa continuous-integration Pending
Review via email: mp+296879@code.launchpad.net

Commit message

moving unity8 helpers to ubuntu system tests helpers. @run_tests: ubuntu_system_tests.tests.indicators.test_indicator_sound.SoundIndicatorTestCase.test_sound_settings_item_open_correct_page

To post a comment you must log in.
396. By Sergio Cazzolato

Adding missing files

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Needs Fixing (continuous-integration)
397. By Sergio Cazzolato

minor fix to start unity8

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Sergio Cazzolato (sergio-j-cazzolato) wrote :

Tested with these tests, and running sanity test list now:

ubuntu_system_tests.tests.test_rotation.RotationTestCase.test_rotation_lock_unlock
ubuntu_system_tests.tests.scopes.test_default_scopes

398. By Sergio Cazzolato

fix in selftests

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Needs Fixing (continuous-integration)
399. By Sergio Cazzolato

minor change to trigger rebuild

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Needs Fixing (continuous-integration)
400. By Sergio Cazzolato

reducing complexity of set_orientation method, because it is failing in jenkins execution but not here

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Needs Fixing (continuous-integration)
401. By Sergio Cazzolato

reducing even more the complexity of set_orientation method

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Needs Fixing (continuous-integration)
402. By Sergio Cazzolato

minor fix for flake8

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Richard Huddie (rhuddie) wrote :

Thanks for this, seems to be working well. I've added some fairly minor comments below.

I did see this failure on some of the scope tests: http://pastebin.ubuntu.com/17139412/

review: Needs Fixing
Revision history for this message
Santiago Baldassin (sbaldassin) wrote :

Thanks for the mp Sergio. I'm adding partial review comments. I'll try to go through the rest of the mp during the day

review: Needs Fixing
403. By Sergio Cazzolato

Updating get_dash method to use patched_select_single

Revision history for this message
Sergio Cazzolato (sergio-j-cazzolato) wrote :

I pushed a change to fix the dash issue. Then I'll go over the other comments.

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Needs Fixing (continuous-integration)

Unmerged revisions

403. By Sergio Cazzolato

Updating get_dash method to use patched_select_single

402. By Sergio Cazzolato

minor fix for flake8

401. By Sergio Cazzolato

reducing even more the complexity of set_orientation method

400. By Sergio Cazzolato

reducing complexity of set_orientation method, because it is failing in jenkins execution but not here

399. By Sergio Cazzolato

minor change to trigger rebuild

398. By Sergio Cazzolato

fix in selftests

397. By Sergio Cazzolato

minor fix to start unity8

396. By Sergio Cazzolato

Adding missing files

395. By Sergio Cazzolato

moving unity8 helpers to ubuntu system tests helpers

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/control'
2--- debian/control 2016-05-10 16:47:27 +0000
3+++ debian/control 2016-06-10 02:06:42 +0000
4@@ -9,8 +9,7 @@
5 python3-fixtures,
6 python3-flake8,
7 python3-setuptools,
8- python3-testscenarios,
9- unity8-autopilot
10+ python3-testscenarios
11 Standards-Version: 3.9.5
12 Homepage: http://launchpad.net/ubuntu-system-tests
13 X-Python3-Version: >= 3.3
14@@ -71,6 +70,5 @@
15 ${python3:Depends},
16 python3-autopilot,
17 ubuntu-system-tests-common,
18- unity8-autopilot,
19 Description: Ubuntu-system-tests test suite and test data
20 This package contains test suites and test data for ubuntu-system-tests.
21
22=== modified file 'debian/tests/control'
23--- debian/tests/control 2016-05-26 14:25:26 +0000
24+++ debian/tests/control 2016-06-10 02:06:42 +0000
25@@ -35,7 +35,6 @@
26 ubuntu-system-tests-helpers,
27 ubuntu-system-tests-suite,
28 unity8,
29- unity8-autopilot (>=8.02+15.04.20150224-0ubuntu1),
30 unity-scope-click,
31 unity-scope-click-autopilot,
32 usbutils,
33
34=== modified file 'ubuntu_system_tests/helpers/indicators/message.py'
35--- ubuntu_system_tests/helpers/indicators/message.py 2016-06-01 15:04:34 +0000
36+++ ubuntu_system_tests/helpers/indicators/message.py 2016-06-10 02:06:42 +0000
37@@ -17,8 +17,7 @@
38 # along with this program. If not, see <http://www.gnu.org/licenses/>.
39
40 import logging
41-
42-from autopilot import logging as autopilot_logging
43+import autopilot
44
45 import ubuntuuitoolkit as uuitk
46
47@@ -136,12 +135,12 @@
48 """Return the contact's avatar icon."""
49 return self.select_single('Icon', objectName='avatar', visible=True)
50
51- @autopilot_logging.log_action(logger.info)
52+ @autopilot.logging.log_action(logger.info)
53 def call(self):
54 """Press the call icon."""
55 self.pointing_device.click_object(self.get_call_icon())
56
57- @autopilot_logging.log_action(logger.info)
58+ @autopilot.logging.log_action(logger.info)
59 def press_avatar(self):
60 """Press the contact's avatar to display snap decision menu."""
61 self.pointing_device.click_object(self.get_contact_avatar())
62
63=== modified file 'ubuntu_system_tests/helpers/indicators/utils.py'
64--- ubuntu_system_tests/helpers/indicators/utils.py 2016-06-08 08:07:44 +0000
65+++ ubuntu_system_tests/helpers/indicators/utils.py 2016-06-10 02:06:42 +0000
66@@ -19,10 +19,9 @@
67
68 import logging
69
70-from unity8 import indicators
71-
72 from ubuntu_system_tests.helpers import context
73 from ubuntu_system_tests.helpers.ubuntuuitoolkit._qquicklistview import QQuickListView # NOQA
74+from ubuntu_system_tests.helpers.unity8 import indicators
75
76 INDICATOR_PAGE_PATH = b'IndicatorPage'
77
78
79=== modified file 'ubuntu_system_tests/helpers/mediascanner.py'
80--- ubuntu_system_tests/helpers/mediascanner.py 2016-04-13 15:02:39 +0000
81+++ ubuntu_system_tests/helpers/mediascanner.py 2016-06-10 02:06:42 +0000
82@@ -21,11 +21,11 @@
83 import dbus
84 import logging
85
86-from unity8 import process_helpers
87-
88 from ubuntu_system_tests.helpers.dbus_observer import DBusObserver
89+from ubuntu_system_tests.helpers import processes
90 from ubuntu_system_tests.helpers.threads import StoppingThread
91
92+
93 MEDIA_SCANNER = 'mediascanner-2.0'
94 MATCH_STRING = ("type='method_call',"
95 "path='/com/canonical/MediaScanner2/Extractor',"
96@@ -38,14 +38,14 @@
97
98 def stop_media_scanner():
99 """ Stop the media scanner process """
100- if process_helpers.is_job_running(MEDIA_SCANNER):
101- process_helpers.stop_job(MEDIA_SCANNER)
102+ if processes.is_job_running(MEDIA_SCANNER):
103+ processes.stop_job(MEDIA_SCANNER)
104
105
106 def start_media_scanner():
107 """ Start the media scanner process """
108- if not process_helpers.is_job_running(MEDIA_SCANNER):
109- process_helpers.start_job(MEDIA_SCANNER)
110+ if not processes.is_job_running(MEDIA_SCANNER):
111+ processes.start_job(MEDIA_SCANNER)
112
113
114 class MediaScannerObserver(DBusObserver):
115
116=== modified file 'ubuntu_system_tests/helpers/processes.py'
117--- ubuntu_system_tests/helpers/processes.py 2016-05-12 16:41:19 +0000
118+++ ubuntu_system_tests/helpers/processes.py 2016-06-10 02:06:42 +0000
119@@ -25,13 +25,15 @@
120
121 import psutil
122
123-from unity8.process_helpers import get_job_status
124-
125 from ubuntu_system_tests.helpers import wait_until
126
127 logger = logging.getLogger(__name__)
128
129
130+class JobError(Exception):
131+ pass
132+
133+
134 def is_process_running(pname):
135 try:
136 return bool(get_process_ids(pname))
137@@ -117,3 +119,82 @@
138 """ Retrieve the command line used to start the process """
139 return subprocess.check_output('xargs -0 < /proc/{}/cmdline'.format(pid),
140 shell=True, universal_newlines=True)
141+
142+
143+def start_job(name, *args):
144+ """Start a job.
145+ :param str name: The name of the job.
146+ :param args: The arguments to be used when starting the job.
147+ :return: The process id of the started job.
148+ :raises CalledProcessError: if the job failed to start.
149+ """
150+ logger.info('Starting job {} with arguments {}.'.format(name, args))
151+ command = ['/sbin/initctl', 'start', name] + list(args)
152+ try:
153+ output = subprocess.check_output(
154+ command,
155+ stderr=subprocess.STDOUT,
156+ universal_newlines=True,
157+ )
158+ logger.info(output)
159+ pid = get_job_pid(name)
160+ except subprocess.CalledProcessError as e:
161+ e.args += ('Failed to start {}: {}.'.format(name, e.output),)
162+ raise
163+ else:
164+ return pid
165+
166+
167+def get_job_pid(name):
168+ """Return the process id of a running job.
169+ :param str name: The name of the job.
170+ :raises JobError: if the job is not running.
171+ """
172+ status = get_job_status(name)
173+ if "start/" not in status:
174+ raise JobError('{} is not in the running state.'.format(name))
175+ return int(status.split()[-1])
176+
177+
178+def get_job_status(name):
179+ """Return the status of a job.
180+ :param str name: The name of the job.
181+ :raises JobError: if it's not possible to get the status of the job.
182+ """
183+ try:
184+ return subprocess.check_output([
185+ '/sbin/initctl',
186+ 'status',
187+ name
188+ ], universal_newlines=True)
189+ except subprocess.CalledProcessError as error:
190+ raise JobError(
191+ "Unable to get {}'s status: {}".format(name, error)
192+ )
193+
194+
195+def stop_job(name):
196+ """Stop a job.
197+ :param str name: The name of the job.
198+ :raises CalledProcessError: if the job failed to stop.
199+ """
200+ logger.info('Stopping job {}.'.format(name))
201+ command = ['/sbin/initctl', 'stop', name]
202+ try:
203+ output = subprocess.check_output(
204+ command,
205+ stderr=subprocess.STDOUT,
206+ universal_newlines=True,
207+ )
208+ logger.info(output)
209+ except subprocess.CalledProcessError as e:
210+ e.args += ('Failed to stop {}: {}.'.format(name, e.output),)
211+ raise
212+
213+
214+def is_job_running(name):
215+ """Return True if the job is running. Otherwise, False.
216+ :param str name: The name of the job.
217+ :raises JobError: if it's not possible to get the status of the job.
218+ """
219+ return 'start/' in get_job_status(name)
220
221=== modified file 'ubuntu_system_tests/helpers/scopes/apps/_preview.py'
222--- ubuntu_system_tests/helpers/scopes/apps/_preview.py 2016-04-19 18:39:43 +0000
223+++ ubuntu_system_tests/helpers/scopes/apps/_preview.py 2016-06-10 02:06:42 +0000
224@@ -19,12 +19,12 @@
225 #
226
227 from autopilot import introspection
228-from unity8.dash import Preview as DashPreview
229
230 from ubuntu_system_tests.helpers.autopilot import (
231 get_path_root, wait_select_single)
232 from ubuntu_system_tests.helpers.scopes.apps import _clickscope
233 from ubuntu_system_tests.helpers.unity8 import UNITY8_DASH_PATH_ROOT
234+from ubuntu_system_tests.helpers.unity8.dash import Preview as DashPreview
235
236
237 class Preview(DashPreview):
238
239=== modified file 'ubuntu_system_tests/helpers/scopes/base.py'
240--- ubuntu_system_tests/helpers/scopes/base.py 2016-04-19 10:06:01 +0000
241+++ ubuntu_system_tests/helpers/scopes/base.py 2016-06-10 02:06:42 +0000
242@@ -22,11 +22,11 @@
243
244 from autopilot import exceptions
245 from collections import namedtuple
246-from unity8 import dash as unity8_dash
247
248 from ubuntu_system_tests.helpers.autopilot.list import order_by_y_coord
249 from ubuntu_system_tests.helpers.ubuntuuitoolkit.pageheader import (
250 DashPageHeader)
251+from ubuntu_system_tests.helpers.unity8 import dash
252 from ubuntu_system_tests.helpers.url_dispatcher import go_to_url
253
254 ScopeDataItem = namedtuple('ScopeDataItem', ['data', 'globalRect'])
255@@ -36,7 +36,7 @@
256 logger = logging.getLogger(__name__)
257
258
259-class GenericScopeView(unity8_dash.GenericScopeView):
260+class GenericScopeView(dash.GenericScopeView):
261 """
262 This class is a base class for all scope CPOs and should never be
263 instantiated directly. This avoids autopilot CPO errors.
264
265=== modified file 'ubuntu_system_tests/helpers/scopes/music/_preview.py'
266--- ubuntu_system_tests/helpers/scopes/music/_preview.py 2016-02-03 16:09:24 +0000
267+++ ubuntu_system_tests/helpers/scopes/music/_preview.py 2016-06-10 02:06:42 +0000
268@@ -18,9 +18,9 @@
269 # along with this program. If not, see <http://www.gnu.org/licenses/>.
270 #
271
272-from unity8.dash import Preview as DashPreview
273-from ubuntu_system_tests.helpers.autopilot.object import \
274- wait_until_is_not_moving
275+from ubuntu_system_tests.helpers.autopilot.object import (
276+ wait_until_is_not_moving)
277+from ubuntu_system_tests.helpers.unity8.dash import Preview as DashPreview
278
279
280 class Preview(DashPreview):
281
282=== modified file 'ubuntu_system_tests/helpers/sensors.py'
283--- ubuntu_system_tests/helpers/sensors.py 2016-04-25 19:02:31 +0000
284+++ ubuntu_system_tests/helpers/sensors.py 2016-06-10 02:06:42 +0000
285@@ -21,11 +21,12 @@
286 import os
287 import subprocess
288
289-from unity8.sensors import FakePlatformSensors as Unity8Sensors
290-
291 from ubuntu_system_tests.helpers import context
292 from ubuntu_system_tests.helpers.power import write_to_powerd_fifo
293 from ubuntu_system_tests.helpers.testbed import run_command_with_sudo as sudo
294+from ubuntu_system_tests.helpers.unity8.sensors import (
295+ FakePlatformSensors as Unity8Sensors)
296+
297
298 DELAY_MS = 10
299 ACCEL_SENSOR_RESOLUTION = 0.1
300
301=== modified file 'ubuntu_system_tests/helpers/ubuntuuitoolkit/slider.py'
302--- ubuntu_system_tests/helpers/ubuntuuitoolkit/slider.py 2015-09-22 10:20:55 +0000
303+++ ubuntu_system_tests/helpers/ubuntuuitoolkit/slider.py 2016-06-10 02:06:42 +0000
304@@ -18,7 +18,7 @@
305 # along with this program. If not, see <http://www.gnu.org/licenses/>.
306
307
308-from unity8 import indicators
309+from ubuntu_system_tests.helpers.unity8 import indicators
310
311
312 class Slider(indicators.Slider):
313
314=== modified file 'ubuntu_system_tests/helpers/unity8/__init__.py'
315--- ubuntu_system_tests/helpers/unity8/__init__.py 2016-06-02 11:07:46 +0000
316+++ ubuntu_system_tests/helpers/unity8/__init__.py 2016-06-10 02:06:42 +0000
317@@ -19,12 +19,22 @@
318 #
319
320 from ubuntu_system_tests.helpers.unity8.utils import (
321+ UnityException,
322 close_all_apps,
323 close_app,
324 ensure_unity_running_and_greeter_hidden,
325 ensure_unity_stopped,
326+ get_binary_path,
327 get_dash,
328+ get_data_dirs,
329+ get_default_extra_mock_libraries,
330+ get_lib_path,
331+ get_mocks_library_path,
332+ get_unity_pid,
333 launch_application_from_launcher,
334+ restart_unity,
335+ restart_unity_with_testability,
336+ running_installed_tests,
337 PROC_NAME,
338 UNITY8_PATH_ROOT,
339 UNITY8_DASH_PATH_ROOT,
340@@ -33,12 +43,22 @@
341
342
343 __all__ = [
344+ 'UnityException',
345 'close_all_apps',
346 'close_app',
347 'ensure_unity_running_and_greeter_hidden',
348 'ensure_unity_stopped',
349+ 'get_binary_path',
350 'get_dash',
351+ 'get_data_dirs',
352+ 'get_default_extra_mock_libraries',
353+ 'get_lib_path',
354+ 'get_mocks_library_path',
355+ 'get_unity_pid',
356 'launch_application_from_launcher',
357+ 'restart_unity',
358+ 'restart_unity_with_testability',
359+ 'running_installed_tests',
360 'PROC_NAME',
361 'UNITY8_PATH_ROOT',
362 'UNITY8_DASH_PATH_ROOT',
363
364=== modified file 'ubuntu_system_tests/helpers/unity8/dash.py'
365--- ubuntu_system_tests/helpers/unity8/dash.py 2016-02-03 16:09:24 +0000
366+++ ubuntu_system_tests/helpers/unity8/dash.py 2016-06-10 02:06:42 +0000
367@@ -18,10 +18,14 @@
368 # along with this program. If not, see <http://www.gnu.org/licenses/>.
369 #
370
371+import logging
372 from retrying import retry
373
374+import autopilot
375 from autopilot.input._common import get_center_point
376-from unity8 import dash as unity8_dash
377+from autopilot.introspection import dbus
378+from ubuntuuitoolkit import (
379+ QQuickFlickable, MainView, UbuntuUIToolkitCustomProxyObjectBase, units)
380
381 from ubuntu_system_tests.helpers.autopilot import (
382 patched_wait_select_single, validate_dbus_object, wait_select_many)
383@@ -29,18 +33,176 @@
384 from ubuntu_system_tests.helpers.ubuntuuitoolkit.pageheader import (
385 DashPageHeader
386 )
387-from ubuntu_system_tests.helpers.unity8 import UNITY8_DASH_PATH_ROOT
388+from ubuntu_system_tests.helpers.unity8 import (
389+ UNITY8_DASH_PATH_ROOT, UnityException)
390
391 SCOPE_CLASS_NAME = 'GenericScopeView'
392
393-
394-class Dash(unity8_dash.Dash):
395+logger = logging.getLogger(__name__)
396+
397+
398+class DashApp():
399+ """Autopilot helper for the Dash app."""
400+
401+ def __init__(self, app_proxy):
402+ self.app_proxy = app_proxy
403+ self.main_view = self.app_proxy.select_single(MainView)
404+ self.dash = self.main_view.select_single(Dash)
405+
406+
407+class Dash(UbuntuUIToolkitCustomProxyObjectBase):
408+
409+ def __init__(self, *args):
410+ super().__init__(*args)
411+ self.dash_content_list = self.wait_select_single(
412+ 'QQuickListView', objectName='dashContentList')
413
414 @classmethod
415 def validate_dbus_object(cls, path, state):
416 return validate_dbus_object(
417 path, state, UNITY8_DASH_PATH_ROOT, b'Dash', objectName='dash')
418
419+ def get_applications_grid(self):
420+ get_grid = self.get_scope('clickscope').wait_select_single(
421+ 'CardGrid', objectName='local')
422+ return get_grid
423+
424+ def get_application_icon(self, text):
425+ """Returns a 'Tile' icon that has the text 'text' from the application
426+ grid.
427+
428+ :param text: String containing the text of the icon to search for.
429+
430+ """
431+ app_grid = self.get_applications_grid()
432+ resp_grid = app_grid.wait_select_single('ResponsiveGridView')
433+ return resp_grid.select_single('Tile', text=text)
434+
435+ def get_scope(self, scope_name='clickscope'):
436+ return self.dash_content_list.wait_select_single(
437+ 'QQuickLoader', scopeId=scope_name)
438+
439+ def get_scope_by_index(self, scope_index=0):
440+ return self.dash_content_list.wait_select_single(
441+ 'QQuickLoader', objectName=("scopeLoader%i" % scope_index))
442+
443+ @autopilot.logging.log_action(logger.info)
444+ def open_scope(self, scope_id):
445+ """Open a dash scope.
446+
447+ :parameter scope_id: The id of the scope.
448+ :return: The scope.
449+
450+ """
451+ scope_loader = self._get_scope_loader(scope_id)
452+ if scope_loader.isCurrent:
453+ logger.info('The scope is already open.')
454+ return self._get_scope_from_loader(scope_loader)
455+ else:
456+ return self._open_scope_scrolling(scope_loader)
457+
458+ def _get_scope_loader(self, scope_id):
459+ try:
460+ aux = self.dash_content_list.get_children_by_type('QQuickItem')[0]
461+ for l in aux.get_children_by_type('QQuickLoader'):
462+ if (l.scopeId == scope_id):
463+ return l
464+ raise UnityException(
465+ 'No scope found with id {0}'.format(scope_id))
466+ except dbus.StateNotFoundError:
467+ raise UnityException(
468+ 'No scope found with id {0}'.format(scope_id))
469+
470+ def _get_scope_from_loader(self, loader):
471+ return loader.wait_select_single('GenericScopeView')
472+
473+ def _open_scope_scrolling(self, scope_loader):
474+ scroll = self._get_scroll_direction(scope_loader)
475+
476+ while not scope_loader.isCurrent:
477+ scroll()
478+ self.dash_content_list.moving.wait_for(False)
479+
480+ scope_loader.isCurrent.wait_for(True)
481+ scope = self._get_scope_from_loader(scope_loader)
482+ return scope
483+
484+ def _get_scroll_direction(self, scope_loader):
485+ current_scope_loader = self.dash_content_list.select_single(
486+ 'QQuickLoader', isCurrent=True)
487+ if scope_loader.globalRect.x < current_scope_loader.globalRect.x:
488+ return self._scroll_to_left_scope
489+ elif scope_loader.globalRect.x > current_scope_loader.globalRect.x:
490+ return self._scroll_to_right_scope
491+ else:
492+ raise UnityException('The scope is already open')
493+
494+ @retry(stop_max_attempt_number=3,
495+ wait_fixed=500,
496+ retry_on_exception=lambda exception: (
497+ isinstance(exception, AssertionError)))
498+ @autopilot.logging.log_action(logger.info)
499+ def _scroll_to_left_scope(self):
500+ original_index = self.dash_content_list.currentIndex
501+ dash_content = self.select_single(objectName="dashContent")
502+ x, y, width, height = dash_content.globalRect
503+ # Make the drag range be a multiple of the drag "rate" value.
504+ # Workarounds https://bugs.launchpad.net/mir/+bug/1399690
505+ rate = 5
506+ divisions = 5
507+ jump = (width / divisions) // rate * rate
508+ start_x = x + jump
509+ stop_x = x + jump * (divisions - 1)
510+ start_y = stop_y = y + 1
511+ self.pointing_device.drag(start_x, start_y, stop_x, stop_y, rate)
512+ self.dash_content_list.currentIndex.wait_for(original_index - 1)
513+
514+ @retry(stop_max_attempt_number=3,
515+ wait_fixed=500,
516+ retry_on_exception=lambda exception: (
517+ isinstance(exception, AssertionError)))
518+ @autopilot.logging.log_action(logger.info)
519+ def _scroll_to_right_scope(self):
520+ original_index = self.dash_content_list.currentIndex
521+ dash_content = self.select_single(objectName="dashContent")
522+ x, y, width, height = dash_content.globalRect
523+ # Make the drag range be a multiple of the drag "rate" value.
524+ # Workarounds https://bugs.launchpad.net/mir/+bug/1399690
525+ rate = 5
526+ divisions = 5
527+ jump = (width / divisions) // rate * rate
528+ start_x = x + jump * (divisions - 1)
529+ stop_x = x + jump
530+ start_y = stop_y = y + 1
531+ self.pointing_device.drag(start_x, start_y, stop_x, stop_y, rate)
532+ self.dash_content_list.currentIndex.wait_for(original_index + 1)
533+
534+ def enter_search_query(self, query, keyboard):
535+ current_header = self._get_current_page_header()
536+ search_button = \
537+ current_header.select_single(objectName="search_button")
538+ self.pointing_device.move(
539+ search_button.globalRect.x + search_button.width / 2,
540+ search_button.globalRect.y + search_button.height / 2)
541+ self.pointing_device.click()
542+ headerContainer = current_header.select_single(
543+ objectName="headerContainer")
544+ headerContainer.contentY.wait_for(0)
545+ keyboard.type(query)
546+ self.select_single(
547+ objectName="processingIndicator").visible.wait_for(False)
548+
549+ def get_search_text_field(self):
550+ page_header = self._get_current_page_header()
551+ return page_header.select_single(objectName='searchTextField')
552+
553+ def _get_current_page_header(self):
554+ all_scopes = self.dash_content_list.select_many("GenericScopeView")
555+ for i in all_scopes:
556+ if i.isCurrent:
557+ return i.select_single(objectName="scopePageHeader")
558+ return None
559+
560 def wait_for_processing_to_complete(self, timeout=90):
561 """Wait until the dash is fully loaded"""
562 self.select_single(
563@@ -52,28 +214,6 @@
564 dash_content = self.select_single(objectName='dashContent')
565 dash_content.pageHeaderTotallyVisible.wait_for(True)
566
567- @retry(stop_max_attempt_number=3,
568- wait_fixed=500,
569- retry_on_exception=lambda exception: (
570- isinstance(exception, AssertionError)))
571- def _scroll_to_left_scope(self):
572- """
573- Call parent implementation, retrying in case it raises
574- an exception due to a failed scrolling
575- """
576- super()._scroll_to_left_scope()
577-
578- @retry(stop_max_attempt_number=3,
579- wait_fixed=500,
580- retry_on_exception=lambda exception: (
581- isinstance(exception, AssertionError)))
582- def _scroll_to_right_scope(self):
583- """
584- Call parent implementation, retrying in case it raises
585- an exception due to a failed scrolling
586- """
587- super()._scroll_to_right_scope()
588-
589 def scroll_to_left_scope(self):
590 self._scroll_to_left_scope()
591 self.dash_content_list.moving.wait_for(False)
592@@ -145,3 +285,84 @@
593 ScopesList,
594 objectName='scopesList',
595 visible=True)
596+
597+
598+class ListViewWithPageHeader(QQuickFlickable):
599+
600+ margin_to_swipe_from_bottom = units.gu(4)
601+
602+
603+class GenericScopeView(UbuntuUIToolkitCustomProxyObjectBase):
604+ """Autopilot helper for generic scopes."""
605+
606+ @autopilot.logging.log_action(logger.info)
607+ def open_preview(self, category, app_name, press_duration=0.10):
608+ """Open the preview of an application.
609+
610+ :parameter category: The name of the category where the application is.
611+ :parameter app_name: The name of the application.
612+ :return: The opened preview.
613+
614+ """
615+ # FIXME some categories need a long press in order to see the preview.
616+ # Some categories do not show previews, like recent apps.
617+ # --elopio - 2014-1-14
618+ self.click_scope_item(category, app_name, press_duration)
619+ preview_list = self.wait_select_single(
620+ 'QQuickLoader', objectName='subPageLoader')
621+ preview_list.subPageShown.wait_for(True)
622+ preview_list.x.wait_for(0)
623+ self.get_root_instance().select_single(
624+ objectName='processingIndicator').visible.wait_for(False)
625+ return preview_list.select_single(
626+ Preview, objectName='preview')
627+
628+ @autopilot.logging.log_action(logger.debug)
629+ def click_scope_item(self, category, title, press_duration=0.10):
630+ """Click an item from the scope.
631+
632+ :parameter category: The name of the category where the item is.
633+ :parameter title: The title of the item.
634+
635+ """
636+ category_element = self._get_category_element(category)
637+ icon = category_element.wait_select_single(
638+ 'UCAbstractButton', title=title)
639+ list_view = self.select_single(
640+ ListViewWithPageHeader, objectName='categoryListView')
641+ list_view.swipe_child_into_view(icon)
642+ self.pointing_device.click_object(icon, press_duration=press_duration)
643+
644+ def _get_category_element(self, category):
645+ try:
646+ return self.wait_select_single(
647+ 'DashCategoryBase',
648+ objectName='dashCategory{}'.format(category))
649+ except dbus.StateNotFoundError:
650+ raise UnityException(
651+ 'No category found with name {}'.format(category))
652+
653+ def get_applications(self, category):
654+ """Return the list of applications on a category.
655+
656+ :parameter category: The name of the category.
657+
658+ """
659+ category_element = self._get_category_element(category)
660+ see_all = category_element.select_single(objectName='seeAll')
661+ application_cards = category_element.select_many('UCAbstractButton')
662+
663+ application_cards = sorted(
664+ (card for card in application_cards
665+ if card.globalRect.y < see_all.globalRect.y),
666+ key=lambda card: (card.globalRect.y, card.globalRect.x))
667+
668+ result = []
669+ for card in application_cards:
670+ if card.objectName not in ('cardToolCard', 'seeAll'):
671+ result.append(card.title)
672+ return result
673+
674+
675+class Preview(UbuntuUIToolkitCustomProxyObjectBase):
676+ """Autopilot custom proxy object for generic previews."""
677
678=== modified file 'ubuntu_system_tests/helpers/unity8/fixture_setup.py'
679--- ubuntu_system_tests/helpers/unity8/fixture_setup.py 2015-05-21 18:15:40 +0000
680+++ ubuntu_system_tests/helpers/unity8/fixture_setup.py 2016-06-10 02:06:42 +0000
681@@ -18,9 +18,314 @@
682 # along with this program. If not, see <http://www.gnu.org/licenses/>.
683 #
684
685+import fixtures
686+import logging
687 import os
688-
689-import fixtures
690+import subprocess
691+import threading
692+
693+import ubuntuuitoolkit
694+from autopilot import introspection
695+from autopilot.matchers import Eventually
696+from testtools.matchers import Equals
697+from ubuntuuitoolkit import fixture_setup
698+
699+from ubuntu_system_tests.helpers import processes
700+from ubuntu_system_tests.helpers.unity8 import (
701+ get_binary_path,
702+ get_mocks_library_path,
703+ get_default_extra_mock_libraries,
704+ get_data_dirs,
705+ get_unity_pid,
706+ restart_unity_with_testability,
707+ sensors
708+)
709+from ubuntu_system_tests.helpers.unity8.shell._cpo import ShellView
710+
711+logger = logging.getLogger(__name__)
712+
713+
714+class LaunchUnityWithFakeSensors(fixtures.Fixture):
715+
716+ """Fixture to launch Unity8 with an injectable sensors backend.
717+
718+ :ivar unity_proxy: The Autopilot proxy object for the Unity shell.
719+
720+ """
721+
722+ unity_proxy = None
723+ main_win = None
724+
725+ def setUp(self):
726+ """Restart Unity8 with testability and create sensors."""
727+ super().setUp()
728+ self.useFixture(
729+ fixture_setup.InitctlEnvironmentVariable(
730+ UBUNTU_PLATFORM_API_TEST_OVERRIDE='sensors'))
731+
732+ self.addCleanup(processes.stop_job, 'unity8')
733+ restart_thread = threading.Thread(
734+ target=self._restart_unity_with_testability)
735+ restart_thread.start()
736+
737+ self._create_sensors()
738+
739+ restart_thread.join()
740+ self.fake_sensors = sensors.FakePlatformSensors()
741+
742+ def _get_lightdm_mock_path(self):
743+ lib_path = get_mocks_library_path()
744+ lightdm_mock_path = os.path.abspath(
745+ os.path.join(lib_path, "IntegratedLightDM", "liblightdm")
746+ )
747+
748+ if not os.path.exists(lightdm_mock_path):
749+ raise RuntimeError(
750+ "LightDM mock does not exist at path {}.".
751+ format(lightdm_mock_path)
752+ )
753+ return lightdm_mock_path
754+
755+ def _get_qml_import_path_with_mock(self):
756+ """Return the QML2_IMPORT_PATH value with the mock path prepended."""
757+ qml_import_path = [get_mocks_library_path()]
758+ if os.getenv('QML2_IMPORT_PATH') is not None:
759+ qml_import_path.append(os.getenv('QML2_IMPORT_PATH'))
760+
761+ qml_import_path = ':'.join(qml_import_path)
762+ return qml_import_path
763+
764+ def _remove_and_ignore_os_error(self, path):
765+ try:
766+ os.unlink(path)
767+ except OSError:
768+ pass
769+
770+ def _restart_unity_with_testability(self):
771+ _environment = {}
772+
773+ data_dirs = get_data_dirs(True)
774+ if data_dirs is not None:
775+ _environment['XDG_DATA_DIRS'] = data_dirs
776+
777+ _environment['QML2_IMPORT_PATH'] = (
778+ self._get_qml_import_path_with_mock()
779+ )
780+
781+ new_ld_library_path = [
782+ get_default_extra_mock_libraries(),
783+ self._get_lightdm_mock_path()
784+ ]
785+ if os.getenv('LD_LIBRARY_PATH') is not None:
786+ new_ld_library_path.append(os.getenv('LD_LIBRARY_PATH'))
787+ new_ld_library_path = ':'.join(new_ld_library_path)
788+ _environment['LD_LIBRARY_PATH'] = new_ld_library_path
789+
790+ # FIXME: we shouldn't be doing this
791+ # $MIR_SOCKET, fallback to $XDG_RUNTIME_DIR/mir_socket and
792+ # /tmp/mir_socket as last resort
793+ self._remove_and_ignore_os_error(
794+ os.getenv('MIR_SOCKET', os.path.join(
795+ os.getenv('XDG_RUNTIME_DIR', "/tmp"), "mir_socket")))
796+ self._remove_and_ignore_os_error("/tmp/mir_socket")
797+
798+ binary_arg = "BINARY=%s" % get_binary_path()
799+ env_args = ["%s=%s" % (k, v) for k, v in _environment.items()]
800+ args = [binary_arg] + env_args
801+ self.unity_proxy = restart_unity_with_testability(*args)
802+ self.main_win = self.unity_proxy.select_single(ShellView)
803+
804+ def _create_sensors(self):
805+ # Wait for unity to start running.
806+ Eventually(Equals(True)).match(
807+ lambda: processes.is_job_running('unity8'))
808+
809+ # Wait for the sensors fifo file to be created.
810+ fifo_path = '/tmp/sensor-fifo-{0}'.format(
811+ get_unity_pid())
812+ Eventually(Equals(True)).match(
813+ lambda: os.path.exists(fifo_path))
814+
815+ with open(fifo_path, 'w') as fifo:
816+ fifo.write('create accel 0 1000 0.1\n')
817+ fifo.write('create light 0 10 1\n')
818+ fifo.write('create proximity\n')
819+
820+
821+class RestartUnityWithTestability(fixtures.Fixture):
822+
823+ """Fixture to launch Unity8 with testability.
824+
825+ :ivar unity_proxy: The Autopilot proxy object for the Unity shell.
826+
827+ """
828+
829+ unity_proxy = None
830+
831+ def __init__(self, binary_path, variables):
832+ """Initialize the fixture instance.
833+
834+ :param str binary_path: The path to the Dash app binary.
835+ :param cli_arguments: The arguments to pass when launching the
836+ :param variables: The variables to use when launching the app.
837+ :type variables: A dictionary.
838+
839+ """
840+ super().__init__()
841+ self.binary_path = binary_path
842+ self.variables = variables
843+
844+ def setUp(self):
845+ """Restart unity with testability when the fixture is used."""
846+ super().setUp()
847+ self.addCleanup(self.stop_unity)
848+ self.restart_unity()
849+
850+ def restart_unity(self):
851+ self.restart_unity_with_testability()
852+
853+ def restart_unity_with_testability(self):
854+ self._unlink_mir_socket()
855+
856+ binary_arg = 'BINARY={}'.format(self.binary_path)
857+ variable_args = [
858+ '{}={}'.format(key, value) for key, value in self.variables.items()
859+ ]
860+ all_args = [binary_arg] + variable_args
861+
862+ self.unity_proxy = restart_unity_with_testability(*all_args)
863+
864+ def _unlink_mir_socket(self):
865+ # FIXME: we shouldn't be doing this
866+ # $MIR_SOCKET, fallback to $XDG_RUNTIME_DIR/mir_socket and
867+ # /tmp/mir_socket as last resort
868+ try:
869+ os.unlink(
870+ os.getenv('MIR_SOCKET',
871+ os.path.join(os.getenv('XDG_RUNTIME_DIR', "/tmp"),
872+ "mir_socket")))
873+ except OSError:
874+ pass
875+ try:
876+ os.unlink("/tmp/mir_socket")
877+ except OSError:
878+ pass
879+
880+ def stop_unity(self):
881+ processes.stop_job('unity8')
882+
883+
884+class LaunchDashApp(fixtures.Fixture):
885+
886+ """Fixture to launch the Dash app."""
887+
888+ def __init__(self, binary_path, variables):
889+ """Initialize an instance.
890+
891+ :param str binary_path: The path to the Dash app binary.
892+ :param variables: The variables to use when launching the app.
893+ :type variables: A dictionary.
894+
895+ """
896+ super().__init__()
897+ self.binary_path = binary_path
898+ self.variables = variables
899+
900+ def setUp(self):
901+ """Launch the dash app when the fixture is used."""
902+ super().setUp()
903+ self.addCleanup(self.stop_application)
904+ self.application_proxy = self.launch_application()
905+
906+ def launch_application(self):
907+ binary_arg = 'BINARY={}'.format(self.binary_path)
908+ testability_arg = 'QT_LOAD_TESTABILITY={}'.format(1)
909+ env_args = [
910+ '{}={}'.format(key, value) for key, value in self.variables.items()
911+ ]
912+ all_args = [binary_arg, testability_arg] + env_args
913+
914+ pid = processes.start_job('unity8-dash', *all_args)
915+ return introspection.get_proxy_object_for_existing_process(
916+ pid=pid,
917+ emulator_base=ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase
918+ )
919+
920+ def stop_application(self):
921+ processes.stop_job('unity8-dash')
922+
923+
924+class DisplayRotationLock(fixtures.Fixture):
925+
926+ def __init__(self, enable):
927+ super().__init__()
928+ self.enable = enable
929+
930+ def setUp(self):
931+ super().setUp()
932+ original_state = self._is_rotation_lock_enabled()
933+ if self.enable != original_state:
934+ self.addCleanup(self._set_rotation_lock, original_state)
935+ self._set_rotation_lock(self.enable)
936+
937+ def _is_rotation_lock_enabled(self):
938+ command = [
939+ 'gsettings', 'get',
940+ 'com.ubuntu.touch.system',
941+ 'rotation-lock'
942+ ]
943+ output = subprocess.check_output(command, universal_newlines=True)
944+ return True if output.count('true') else False
945+
946+ def _set_rotation_lock(self, value):
947+ value_string = 'true' if value else 'false'
948+ command = [
949+ 'gsettings', 'set',
950+ 'com.ubuntu.touch.system',
951+ 'rotation-lock', value_string
952+ ]
953+ subprocess.check_output(command)
954+
955+
956+class LaunchMockIndicatorService(fixtures.Fixture):
957+
958+ """Fixture to launch the indicator test service."""
959+
960+ def __init__(self, action_delay, ensure_not_running=True):
961+ """Initialize an instance.
962+
963+ :param action_delay: The delay to use when activating actions.
964+ Measured in milliseconds. Value of -1 will result in infinite delay.
965+ :type action_delay: An integer.
966+ :param boolean ensure_not_running: Make sure service is not running
967+
968+ """
969+ super(LaunchMockIndicatorService, self).__init__()
970+ self.action_delay = action_delay
971+ self.ensure_not_running = ensure_not_running
972+
973+ def setUp(self):
974+ super().setUp()
975+ if self.ensure_not_running:
976+ self.ensure_service_not_running()
977+ self.addCleanup(self.stop_service)
978+ self.application_proxy = self.launch_service()
979+
980+ def launch_service(self):
981+ logger.info("Starting unity-mock-indicator-service")
982+ binary_path = get_binary_path('unity-mock-indicator-service')
983+ binary_arg = 'BINARY={}'.format(binary_path)
984+ env_args = 'ARGS=-t {}'.format(self.action_delay)
985+ all_args = [binary_arg, env_args]
986+ processes.start_job('unity-mock-indicator-service', *all_args)
987+
988+ def stop_service(self):
989+ logger.info("Stopping unity-mock-indicator-service")
990+ processes.stop_job('unity-mock-indicator-service')
991+
992+ def ensure_service_not_running(self):
993+ if processes.is_job_running('unity-mock-indicator-service'):
994+ self.stop_service()
995
996
997 class SettingsWizard(fixtures.Fixture):
998
999=== modified file 'ubuntu_system_tests/helpers/unity8/greeter.py'
1000--- ubuntu_system_tests/helpers/unity8/greeter.py 2016-04-18 17:29:42 +0000
1001+++ ubuntu_system_tests/helpers/unity8/greeter.py 2016-06-10 02:06:42 +0000
1002@@ -19,14 +19,21 @@
1003 #
1004
1005 import dbus
1006+
1007 from autopilot.matchers import Eventually
1008+from autopilot.utilities import sleep
1009 from testtools.matchers import Equals
1010+from ubuntuuitoolkit import UbuntuUIToolkitCustomProxyObjectBase, TextField
1011
1012
1013 def wait_for_greeter():
1014 Eventually(Equals(True), timeout=300).match(_is_greeter_active)
1015
1016
1017+def wait_for_greeter_gone():
1018+ Eventually(Equals(False), timeout=300).match(_is_greeter_active)
1019+
1020+
1021 def _is_greeter_active():
1022 try:
1023 dbus_proxy = _get_greeter_dbus_proxy()
1024@@ -50,3 +57,55 @@
1025 dbus_proxy = _get_greeter_dbus_proxy()
1026 if not _is_greeter_active():
1027 dbus_proxy.ShowGreeter()
1028+
1029+
1030+def unlock_unity():
1031+ """Helper function that attempts to unlock the unity greeter. """
1032+ wait_for_greeter()
1033+ hide_greeter_with_dbus()
1034+ wait_for_greeter_gone()
1035+
1036+
1037+def lock_unity():
1038+ """Helper function that attempts to lock unity greeter. """
1039+ show_greeter_with_dbus()
1040+ wait_for_greeter()
1041+
1042+
1043+class Greeter(UbuntuUIToolkitCustomProxyObjectBase):
1044+ """A helper that understands the greeter screen."""
1045+
1046+ def wait_swiped_away(self):
1047+ # We have to be careful here, because coverPage can go away at any time
1048+ # if there isn't a lockscreen behind it (it hides completely, then
1049+ # the greeter disposes it). But if there *is* a lockscreen, then we
1050+ # need a different check, by looking at its showProgress. So make our
1051+ # own wait_for loop and check both possibilities.
1052+ for i in range(10):
1053+ if not self.required:
1054+ return
1055+ coverPage = self.select_single(objectName='coverPage')
1056+ if coverPage.showProgress == 0:
1057+ return
1058+ sleep(1)
1059+
1060+ raise AssertionError("Greeter cover page still up after 10s")
1061+
1062+ def swipe(self):
1063+ """Swipe the greeter screen away."""
1064+ self.waiting.wait_for(False)
1065+ coverPage = self.select_single(objectName='coverPage')
1066+ coverPage.showProgress.wait_for(1)
1067+
1068+ rect = self.globalRect
1069+ start_x = rect[0] + rect[2] - 3
1070+ start_y = int(rect[1] + rect[3] / 2)
1071+ stop_x = int(rect[0] + rect[2] * 0.2)
1072+ stop_y = start_y
1073+ self.pointing_device.drag(start_x, start_y, stop_x, stop_y)
1074+
1075+ self.wait_swiped_away()
1076+
1077+ def get_prompt(self):
1078+ return self.select_single(
1079+ TextField, objectName='passwordInput')
1080
1081=== added file 'ubuntu_system_tests/helpers/unity8/indicators.py'
1082--- ubuntu_system_tests/helpers/unity8/indicators.py 1970-01-01 00:00:00 +0000
1083+++ ubuntu_system_tests/helpers/unity8/indicators.py 2016-06-10 02:06:42 +0000
1084@@ -0,0 +1,179 @@
1085+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
1086+
1087+#
1088+# Ubuntu System Tests
1089+# Copyright (C) 2016 Canonical
1090+#
1091+# This program is free software: you can redistribute it and/or modify
1092+# it under the terms of the GNU General Public License as published by
1093+# the Free Software Foundation, either version 3 of the License, or
1094+# (at your option) any later version.
1095+#
1096+# This program is distributed in the hope that it will be useful,
1097+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1098+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1099+# GNU General Public License for more details.
1100+#
1101+# You should have received a copy of the GNU General Public License
1102+# along with this program. If not, see <http://www.gnu.org/licenses/>.
1103+#
1104+
1105+from autopilot import introspection
1106+from ubuntuuitoolkit import (
1107+ UbuntuUIToolkitCustomProxyObjectBase, CheckBox, QQuickFlickable)
1108+
1109+
1110+class IndicatorPage(UbuntuUIToolkitCustomProxyObjectBase):
1111+
1112+ """Autopilot helper for the IndicatorPage component."""
1113+
1114+ # XXX Because of https://bugs.launchpad.net/autopilot-qt/+bug/1341671
1115+ # we need to make sure it does not match in any selection.
1116+ # --elopio - 2015-01-20
1117+
1118+ @classmethod
1119+ def validate_dbus_object(cls, path, state):
1120+ return False
1121+
1122+
1123+class Indicator():
1124+
1125+ def __init__(self, main_window, name):
1126+ self._main_window = main_window
1127+ self._name = name
1128+
1129+ def is_indicator_icon_visible(self):
1130+ panel_item = self._main_window.wait_select_single(
1131+ objectName=self._name+'-panelItem')
1132+ return panel_item.indicatorVisible
1133+
1134+ def open(self):
1135+ """Open the indicator page.
1136+
1137+ :return: The custom proxy object for the indicator page.
1138+
1139+ """
1140+ if self.is_indicator_icon_visible():
1141+ return self._main_window.open_indicator_page(self._name)
1142+ else:
1143+ return self._open_indicator_with_icon_not_visible()
1144+
1145+ def _open_indicator_with_icon_not_visible(self):
1146+ # Open any displayed indicator.
1147+ self._main_window.open_indicator_page('indicator-datetime')
1148+ self._make_indicator_icon_visible()
1149+ indicator_rotation_icon = self._main_window.select_single(
1150+ objectName=self._name+'-panelItem')
1151+ self._main_window.pointing_device.click_object(indicator_rotation_icon)
1152+ return self._main_window.wait_select_single(
1153+ objectName=self._name+'-page')
1154+
1155+ def _make_indicator_icon_visible(self):
1156+ indicators_bar = self._main_window.select_single('IndicatorsBar')
1157+ indicators_bar_flickable = indicators_bar.select_single(
1158+ QQuickFlickable, objectName='flickable')
1159+ self._swipe_flickable_to_x_end(indicators_bar_flickable)
1160+
1161+ def _swipe_flickable_to_x_end(self, flickable):
1162+ # XXX this should be implemented as a general horizontal swiping in
1163+ # the toolkit custom proxy object. -- elopio - 2015-01-20
1164+ if not flickable.atXEnd:
1165+ flickable.interactive.wait_for(True)
1166+ while not flickable.atXEnd:
1167+ start_y = stop_y = (
1168+ flickable.globalRect.y +
1169+ (flickable.globalRect.height // 2))
1170+ # We can't start the swipe from the border because it would
1171+ # open the launcher
1172+ start_x = flickable.globalRect.x + 45
1173+ stop_x = (
1174+ flickable.globalRect.x + flickable.globalRect.width - 5)
1175+ flickable.pointing_device.drag(
1176+ start_x, start_y, stop_x, stop_y)
1177+ flickable.dragging.wait_for(False)
1178+ flickable.moving.wait_for(False)
1179+
1180+ def close(self):
1181+ """Close the indicator page."""
1182+ self._main_window.close_indicator_page()
1183+
1184+
1185+class DisplayIndicator(Indicator):
1186+
1187+ def __init__(self, main_window):
1188+ super(DisplayIndicator, self).__init__(main_window,
1189+ 'indicator-rotation-lock')
1190+ self._main_window = main_window
1191+
1192+
1193+class DisplayIndicatorPage(IndicatorPage):
1194+
1195+ """Autopilot helper for the display indicator page."""
1196+
1197+ @classmethod
1198+ def validate_dbus_object(cls, path, state):
1199+ name = introspection.get_classname_from_path(path)
1200+ if name == b'IndicatorPage':
1201+ if state['objectName'][1] == 'indicator-rotation-lock-page':
1202+ return True
1203+ return False
1204+
1205+ def lock_rotation(self):
1206+ """Toggle the rotation lock indicator to locked."""
1207+ switcher = self._get_switcher()
1208+ switcher.check()
1209+ switcher.checked.wait_for(True)
1210+
1211+ def _get_switcher(self):
1212+ return self.select_single(
1213+ CheckBox, objectName='switcher')
1214+
1215+ def unlock_rotation(self):
1216+ """Toggle the rotation lock indicator to unlocked."""
1217+ switcher = self._get_switcher()
1218+ switcher.uncheck()
1219+ switcher.checked.wait_for(False)
1220+
1221+
1222+class TestIndicator(Indicator):
1223+
1224+ def __init__(self, main_window):
1225+ super(TestIndicator, self).__init__(main_window, 'indicator-mock')
1226+ self._main_window = main_window
1227+
1228+
1229+class Slider(UbuntuUIToolkitCustomProxyObjectBase):
1230+ """Autopilot helper for the Slider component."""
1231+
1232+ # XXX Because of https://bugs.launchpad.net/autopilot-qt/+bug/1341671
1233+ # we need to make sure it does not match in any selection.
1234+ # --elopio - 2015-01-20
1235+
1236+ @classmethod
1237+ def validate_dbus_object(cls, path, state):
1238+ name = introspection.get_classname_from_path(path)
1239+ if name == b'Slider':
1240+ return True
1241+ return False
1242+
1243+ def slide_left(self, timeout=10):
1244+ x, y, width, height = self.globalRect
1245+
1246+ rate = 5
1247+ start_x = x + width/2
1248+ start_y = stop_y = y + height/2
1249+ stop_x = x
1250+
1251+ self.pointing_device.drag(start_x, start_y, stop_x, stop_y, rate)
1252+ self.value.wait_for(self.minimumValue, timeout)
1253+
1254+ def slide_right(self, timeout=10):
1255+ x, y, width, height = self.globalRect
1256+
1257+ rate = 5
1258+ start_x = x + width/2
1259+ start_y = stop_y = y + height/2
1260+ stop_x = x + width
1261+
1262+ self.pointing_device.drag(start_x, start_y, stop_x, stop_y, rate)
1263+ self.value.wait_for(self.maximumValue, timeout)
1264
1265=== added file 'ubuntu_system_tests/helpers/unity8/launcher.py'
1266--- ubuntu_system_tests/helpers/unity8/launcher.py 1970-01-01 00:00:00 +0000
1267+++ ubuntu_system_tests/helpers/unity8/launcher.py 2016-06-10 02:06:42 +0000
1268@@ -0,0 +1,66 @@
1269+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
1270+
1271+#
1272+# Ubuntu System Tests
1273+# Copyright (C) 2016 Canonical
1274+#
1275+# This program is free software: you can redistribute it and/or modify
1276+# it under the terms of the GNU General Public License as published by
1277+# the Free Software Foundation, either version 3 of the License, or
1278+# (at your option) any later version.
1279+#
1280+# This program is distributed in the hope that it will be useful,
1281+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1282+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1283+# GNU General Public License for more details.
1284+#
1285+# You should have received a copy of the GNU General Public License
1286+# along with this program. If not, see <http://www.gnu.org/licenses/>.
1287+#
1288+
1289+import logging
1290+
1291+import autopilot.logging
1292+import ubuntuuitoolkit
1293+
1294+from ubuntu_system_tests.helpers import unity8
1295+
1296+logger = logging.getLogger(__name__)
1297+
1298+
1299+class Launcher(ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase):
1300+
1301+ """A helper that understands the Launcher."""
1302+
1303+ @autopilot.logging.log_action(logger.debug)
1304+ def show(self):
1305+ """Show the launcher swiping it to the right."""
1306+ if not self.shown:
1307+ self._swipe_to_show_launcher()
1308+ self.shown.wait_for(True)
1309+ else:
1310+ logger.debug('The launcher is already opened.')
1311+
1312+ def _swipe_to_show_launcher(self):
1313+ view = self.get_root_instance().select_single('ShellView')
1314+ start_y = stop_y = view.y + view.height // 2
1315+
1316+ start_x = view.x + 1
1317+ stop_x = start_x + self.panelWidth - 1
1318+
1319+ self.pointing_device.drag(start_x, start_y, stop_x, stop_y)
1320+
1321+ @autopilot.logging.log_action(logger.debug)
1322+ def click_dash_icon(self):
1323+ if self.shown:
1324+ dash_icon = self.select_single(
1325+ 'QQuickImage', objectName='dashItem')
1326+ self.pointing_device.click_object(dash_icon)
1327+ else:
1328+ raise unity8.UnityException('The launcher is closed.')
1329+
1330+ @autopilot.logging.log_action(logger.debug)
1331+ def click_application_launcher_icon(self, application_name):
1332+ launcher_delegate = self.select_single(
1333+ 'LauncherDelegate', appId=application_name)
1334+ self.pointing_device.click_object(launcher_delegate)
1335
1336=== modified file 'ubuntu_system_tests/helpers/unity8/phone_stage.py'
1337--- ubuntu_system_tests/helpers/unity8/phone_stage.py 2016-04-27 21:43:27 +0000
1338+++ ubuntu_system_tests/helpers/unity8/phone_stage.py 2016-06-10 02:06:42 +0000
1339@@ -20,7 +20,7 @@
1340
1341 import logging
1342
1343-from autopilot import logging as autopilot_logging
1344+import autopilot
1345 from autopilot.exceptions import StateNotFoundError
1346 from ubuntuuitoolkit import UbuntuUIToolkitCustomProxyObjectBase
1347 from ubuntu_system_tests.helpers.autopilot import validate_dbus_object
1348@@ -80,14 +80,14 @@
1349 mid_x = x + ((next_x - x) // 4)
1350 return mid_x, mid_y
1351
1352- @autopilot_logging.log_action(logger.info)
1353+ @autopilot.logging.log_action(logger.info)
1354 def _press_app(self, app_window):
1355 """Press on the required app_window object."""
1356 x, y = self._get_app_window_touch_point(app_window)
1357 self.pointing_device.move(x, y)
1358 self.pointing_device.click()
1359
1360- @autopilot_logging.log_action(logger.info)
1361+ @autopilot.logging.log_action(logger.info)
1362 def _swipe_from_app_to_right_edge(self, app_window):
1363 """Swipe from the required app_window object to right screen edge."""
1364 start_x, start_y = self._get_app_window_touch_point(app_window)
1365@@ -95,7 +95,7 @@
1366 end_y = start_y
1367 self.pointing_device.drag(start_x, start_y, end_x, end_y, rate=3)
1368
1369- @autopilot_logging.log_action(logger.info)
1370+ @autopilot.logging.log_action(logger.info)
1371 def _swipe_from_app_to_top_edge(self, app_window):
1372 """Swipe from the required app_window object to top screen edge."""
1373 start_x, start_y = self._get_app_window_touch_point(app_window)
1374@@ -103,7 +103,7 @@
1375 end_y = 0
1376 self.pointing_device.drag(start_x, start_y, end_x, end_y)
1377
1378- @autopilot_logging.log_action(logger.info)
1379+ @autopilot.logging.log_action(logger.info)
1380 def _swipe_from_right(self):
1381 """Swipe from right edge to reveal the application switcher"""
1382 width = self.width
1383
1384=== modified file 'ubuntu_system_tests/helpers/unity8/sensors.py'
1385--- ubuntu_system_tests/helpers/unity8/sensors.py 2016-04-25 19:02:31 +0000
1386+++ ubuntu_system_tests/helpers/unity8/sensors.py 2016-06-10 02:06:42 +0000
1387@@ -18,12 +18,95 @@
1388 # along with this program. If not, see <http://www.gnu.org/licenses/>.
1389 #
1390
1391+import logging
1392 import os
1393 import stat
1394
1395 from ubuntu_system_tests.helpers import context
1396 from ubuntu_system_tests.helpers import wait_until
1397 from ubuntu_system_tests.helpers.testbed import write_to_file_with_sudo
1398+from ubuntu_system_tests.helpers import unity8
1399+
1400+logger = logging.getLogger(__name__)
1401+
1402+
1403+class FakePlatformSensors:
1404+
1405+ def __init__(self, pid=None):
1406+ self.pid = pid or unity8.get_unity_pid()
1407+
1408+ def _set_orientation_top_up(self):
1409+ with open("/tmp/sensor-fifo-{0}".format(self.pid), "w") as fifo:
1410+ fifo.write("70 accel -10.050858 -0.598550 0.756568\n")
1411+ fifo.write("70 accel -9.797073 -0.555455 1.019930\n")
1412+ fifo.write("70 accel -10.141838 -0.770933 0.632069\n")
1413+ fifo.write("70 accel -12.057199 -1.259350 1.690306\n")
1414+ fifo.write("70 accel -19.282900 -3.926491 3.098097\n")
1415+ fifo.write("70 accel -14.480132 -14.269443 1.216254\n")
1416+ fifo.write("70 accel 16.419436 4.242526 -7.714118\n")
1417+ fifo.write("70 accel 5.583278 8.279149 -1.848324\n")
1418+ fifo.write("70 accel 1.422156 8.547300 0.416591\n")
1419+ fifo.write("70 accel 4.357447 9.988609 -0.110133\n")
1420+ fifo.write("70 accel 0.699107 9.840169 0.756568\n")
1421+ fifo.write("70 accel 1.364695 9.844957 -0.287304\n")
1422+ fifo.flush()
1423+
1424+ def _set_orientation_top_down(self):
1425+ with open("/tmp/sensor-fifo-{0}".format(self.pid), "w") as fifo:
1426+ fifo.write("70 accel -10.050858 -0.598550 0.756568\n")
1427+ fifo.write("70 accel 9.538500 -0.603339 1.292869\n")
1428+ fifo.write("70 accel 9.485827 -0.636858 1.422156\n")
1429+ fifo.write("70 accel 9.677363 -0.402226 1.374272\n")
1430+ fifo.write("70 accel 9.303867 -0.507571 1.283292\n")
1431+ fifo.write("70 accel 8.604761 -1.015141 1.436521\n")
1432+ fifo.write("70 accel 7.580042 -2.001553 0.521936\n")
1433+ fifo.write("70 accel 7.503428 -4.247314 0.502782\n")
1434+ fifo.write("70 accel 7.067683 -7.240066 0.842759\n")
1435+ fifo.write("70 accel 6.488286 -9.873688 -0.541090\n")
1436+ fifo.write("70 accel 6.229713 -9.241618 -1.048660\n")
1437+ fifo.write("70 accel 4.046201 -9.198523 -0.057461\n")
1438+ fifo.write("70 accel 2.398990 -9.629479 0.957681\n")
1439+ fifo.write("70 accel 1.632846 -9.361329 -0.311246\n")
1440+ fifo.write("70 accel -0.181959 -9.696517 -0.301669\n")
1441+ fifo.flush()
1442+
1443+ def _set_orientation_left_up(self):
1444+ with open("/tmp/sensor-fifo-{0}".format(self.pid), "w") as fifo:
1445+ fifo.write("70 accel -10.050858 -0.598550 0.756568\n")
1446+ fifo.write("70 accel 0.196325 9.878476 0.948104\n")
1447+ fifo.write("70 accel 0.258574 9.955091 1.091756\n")
1448+ fifo.write("70 accel 0.287304 10.041282 1.134852\n")
1449+ fifo.write("70 accel 1.537078 10.553641 1.561020\n")
1450+ fifo.write("70 accel 8.130709 10.093954 2.561796\n")
1451+ fifo.write("70 accel -0.229843 5.348647 1.723825\n")
1452+ fifo.write("70 accel -9.916783 0.488417 -3.418920\n")
1453+ fifo.write("70 accel -13.417107 -0.416591 -2.360683\n")
1454+ fifo.write("70 accel -13.872005 -2.049437 -0.574608\n")
1455+ fifo.flush()
1456+
1457+ def _set_orientation_right_up(self):
1458+ with open("/tmp/sensor-fifo-{0}".format(self.pid), "w") as fifo:
1459+ fifo.write("70 accel -10.050858 -0.598550 0.756568\n")
1460+ fifo.write("70 accel -4.550858 -0.598550 0.856568\n")
1461+ fifo.write("70 accel -0.799663 9.988609 1.197101\n")
1462+ fifo.write("70 accel -0.861913 9.864111 1.066701\n")
1463+ fifo.write("70 accel -0.861913 9.864111 0.866701\n")
1464+ fifo.write("70 accel -1.776498 9.830592 1.273715\n")
1465+ fifo.write("70 accel -2.376498 9.830592 1.273715\n")
1466+ fifo.write("70 accel -13.158532 2.217031 1.091756\n")
1467+ fifo.write("70 accel 5.056554 1.067814 0.799663\n")
1468+ fifo.write("70 accel 5.056554 1.767814 0.799663\n")
1469+ fifo.write("70 accel 14.882358 2.896984 1.221043\n")
1470+ fifo.write("70 accel 9.466674 -0.363919 -1.029507\n")
1471+ fifo.write("70 accel 11.253524 -0.186748 -0.311246\n")
1472+ fifo.write("70 accel 12.253524 -0.186748 -0.311246\n")
1473+ fifo.flush()
1474+
1475+ def set_orientation(self, action):
1476+ try:
1477+ getattr(self, '_set_orientation_{}'.format(action))()
1478+ except AttributeError:
1479+ logger.error('Action {} not defined'.format(action))
1480
1481
1482 def get_unity8_fifo_path():
1483
1484=== added directory 'ubuntu_system_tests/helpers/unity8/shell'
1485=== removed file 'ubuntu_system_tests/helpers/unity8/shell.py'
1486--- ubuntu_system_tests/helpers/unity8/shell.py 2016-06-02 09:12:43 +0000
1487+++ ubuntu_system_tests/helpers/unity8/shell.py 1970-01-01 00:00:00 +0000
1488@@ -1,169 +0,0 @@
1489-# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
1490-
1491-#
1492-# Ubuntu System Tests
1493-# Copyright (C) 2015, 2016 Canonical
1494-#
1495-# This program is free software: you can redistribute it and/or modify
1496-# it under the terms of the GNU General Public License as published by
1497-# the Free Software Foundation, either version 3 of the License, or
1498-# (at your option) any later version.
1499-#
1500-# This program is distributed in the hope that it will be useful,
1501-# but WITHOUT ANY WARRANTY; without even the implied warranty of
1502-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1503-# GNU General Public License for more details.
1504-#
1505-# You should have received a copy of the GNU General Public License
1506-# along with this program. If not, see <http://www.gnu.org/licenses/>.
1507-#
1508-
1509-import logging
1510-
1511-from autopilot import (
1512- exceptions,
1513- logging as autopilot_logging
1514-)
1515-import ubuntuuitoolkit
1516-from unity8.shell.emulators import main_window
1517-
1518-from ubuntu_system_tests.helpers.autopilot import validate_dbus_object
1519-from ubuntu_system_tests.helpers.indicators.message import NotificationsIndicatorPage, NotificationsIndicatorItem # NOQA
1520-from ubuntu_system_tests.helpers.notifications.utils import Notifications
1521-from ubuntu_system_tests.helpers.unity8 import (
1522- greeter as greeter_helpers, UNITY8_PATH_ROOT)
1523-
1524-logger = logging.getLogger(__name__)
1525-
1526-
1527-class Unity8(ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase):
1528-
1529- """Autopilot custom proxy object for the Unity8 shell."""
1530-
1531- @classmethod
1532- def validate_dbus_object(cls, path, state):
1533- return validate_dbus_object(
1534- path, state, UNITY8_PATH_ROOT, UNITY8_PATH_ROOT,
1535- applicationName='unity8')
1536-
1537- @property
1538- def main_window(self):
1539- return self.select_single(ShellView)
1540-
1541- @autopilot_logging.log_action(logger.debug)
1542- def wait_for_greeter_content(self):
1543- greeter = self.main_window.wait_select_single(objectName='greeter')
1544- greeter.waiting.wait_for(False)
1545-
1546- @autopilot_logging.log_action(logger.info)
1547- def unlock(self):
1548- greeter = self.main_window.get_greeter()
1549- if greeter.created:
1550- greeter_helpers.hide_greeter_with_dbus()
1551- greeter.created.wait_for(False)
1552-
1553- def show_dash_from_launcher(self):
1554- self.main_window.show_dash_from_launcher()
1555-
1556- def get_number_of_sessions(self):
1557- application_window = self.select_single('ApplicationWindow')
1558- return len(application_window.select_many('SessionContainer'))
1559-
1560- def get_height(self):
1561- return self.main_window.height
1562-
1563- def get_width(self):
1564- return self.main_window.width
1565-
1566- def ensure_app_loaded(self):
1567- try:
1568- indicator = self.select_single('ActivityIndicator')
1569- indicator.onScreen.wait_for(False)
1570- except exceptions.StateNotFoundError:
1571- # This is fine, it's already loaded
1572- pass
1573-
1574-
1575-class ShellView(main_window.ShellView):
1576- """Class to extend Unity8 main window ShellView."""
1577-
1578- @classmethod
1579- def validate_dbus_object(cls, path, state):
1580- return validate_dbus_object(
1581- path, state, UNITY8_PATH_ROOT, b'ShellView', title='Unity8')
1582-
1583- def get_notifications_list(self):
1584- """Return a list of notifications currently being displayed."""
1585- return self.select_single(
1586- Notifications, objectName='notificationList')
1587-
1588- def get_notifications_panel(self):
1589- """Return 'Notifications' panel object."""
1590- return self._get_indicator_panel_item('indicator-messages')
1591-
1592- def clear_notifications(self):
1593- """
1594- Clear all existing notifications from 'Notifications' indicator.
1595-
1596- """
1597- if self.is_new_notification_displayed():
1598- self.open_indicator_page('indicator-messages').clear_all()
1599- self.close_indicator_page()
1600-
1601- def open_notifications_indicator(self):
1602- """Swipe down to display the notifications indicator."""
1603- return self.open_indicator_page('indicator-messages')
1604-
1605- def is_new_notification_displayed(self):
1606- """Return True if new notification message icon is displayed."""
1607- return self.get_notifications_panel().is_new_message_displayed()
1608-
1609- def get_passphrase_unlock_screen(self):
1610- """Wait for input method to be in shown state and return lockscreen."""
1611- from ubuntu_system_tests.helpers.unity8 import lock_screen
1612- input_method = self.wait_select_single(
1613- 'InputMethod', objectName='inputMethod', visible=True)
1614- input_method.state.wait_for('shown')
1615- return self.select_single(lock_screen.PassphraseLockscreen)
1616-
1617- def get_missed_call_snap_decision(self):
1618- """Return missed call snap decision menu."""
1619- from ubuntu_system_tests.helpers.snap_decision import missed_call
1620- return self.select_single(
1621- missed_call.SnapDecisionMenu, objectName='snapDecision',
1622- visible=True)
1623-
1624- def get_phone_stage(self):
1625- from ubuntu_system_tests.helpers.unity8 import phone_stage
1626- return self.select_single(phone_stage.PhoneStage, objectName='stage')
1627-
1628- def swipe_to_show_app_switcher(self):
1629- """Swipe from right edge to reveal task switcher."""
1630- stage = self.get_phone_stage()
1631- stage.swipe_to_top()
1632- return stage
1633-
1634- def get_current_focused_app(self):
1635- """Return Id for current focused app."""
1636- return self.select_single('Shell').focusedApplicationId
1637-
1638- def _is_indicator_panel_opened(self):
1639- indicator_page = self.wait_select_single('IndicatorsMenu')
1640- return indicator_page.fullyOpened
1641-
1642- def close_indicator_page(self):
1643- """
1644- Override the method to only try to close the indicator panel if its
1645- not already.
1646- """
1647- if self._is_indicator_panel_opened():
1648- super().close_indicator_page()
1649-
1650- def is_indicator_item_hidden(self, indicator_name):
1651- """
1652- Return bool representing if the requested indicator item is hidden or
1653- not.
1654- """
1655- item = self.select_single('IndicatorItem',
1656- objectName=indicator_name + '-panelItem')
1657- return item.hidden
1658
1659=== added file 'ubuntu_system_tests/helpers/unity8/shell/__init__.py'
1660--- ubuntu_system_tests/helpers/unity8/shell/__init__.py 1970-01-01 00:00:00 +0000
1661+++ ubuntu_system_tests/helpers/unity8/shell/__init__.py 2016-06-10 02:06:42 +0000
1662@@ -0,0 +1,31 @@
1663+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
1664+
1665+#
1666+# Ubuntu System Tests
1667+# Copyright (C) 2016 Canonical
1668+#
1669+# This program is free software: you can redistribute it and/or modify
1670+# it under the terms of the GNU General Public License as published by
1671+# the Free Software Foundation, either version 3 of the License, or
1672+# (at your option) any later version.
1673+#
1674+# This program is distributed in the hope that it will be useful,
1675+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1676+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1677+# GNU General Public License for more details.
1678+#
1679+# You should have received a copy of the GNU General Public License
1680+# along with this program. If not, see <http://www.gnu.org/licenses/>.
1681+#
1682+
1683+"""unity shell autopilot tests and helpers - sub level package."""
1684+
1685+from ubuntu_system_tests.helpers.unity8.shell.utils import (
1686+ disable_qml_mocking,
1687+ create_ephemeral_notification,
1688+)
1689+
1690+__all__ = [
1691+ 'disable_qml_mocking',
1692+ 'create_ephemeral_notification',
1693+]
1694
1695=== added file 'ubuntu_system_tests/helpers/unity8/shell/_cpo.py'
1696--- ubuntu_system_tests/helpers/unity8/shell/_cpo.py 1970-01-01 00:00:00 +0000
1697+++ ubuntu_system_tests/helpers/unity8/shell/_cpo.py 2016-06-10 02:06:42 +0000
1698@@ -0,0 +1,319 @@
1699+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
1700+
1701+#
1702+# Ubuntu System Tests
1703+# Copyright (C) 2016 Canonical
1704+#
1705+# This program is free software: you can redistribute it and/or modify
1706+# it under the terms of the GNU General Public License as published by
1707+# the Free Software Foundation, either version 3 of the License, or
1708+# (at your option) any later version.
1709+#
1710+# This program is distributed in the hope that it will be useful,
1711+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1712+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1713+# GNU General Public License for more details.
1714+#
1715+# You should have received a copy of the GNU General Public License
1716+# along with this program. If not, see <http://www.gnu.org/licenses/>.
1717+#
1718+
1719+import logging
1720+import autopilot
1721+from autopilot import (
1722+ exceptions,
1723+ input
1724+)
1725+import ubuntuuitoolkit
1726+
1727+from ubuntu_system_tests.helpers.autopilot import validate_dbus_object
1728+from ubuntu_system_tests.helpers.notifications.utils import Notifications
1729+from ubuntu_system_tests.helpers.unity8 import (
1730+ greeter as greeter_helpers, launcher as launcher_helpers, UNITY8_PATH_ROOT)
1731+
1732+logger = logging.getLogger(__name__)
1733+
1734+
1735+class Unity8(ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase):
1736+ """Autopilot custom proxy object for the Unity8 shell."""
1737+
1738+ @classmethod
1739+ def validate_dbus_object(cls, path, state):
1740+ return validate_dbus_object(
1741+ path, state, UNITY8_PATH_ROOT, UNITY8_PATH_ROOT,
1742+ applicationName='unity8')
1743+
1744+ @property
1745+ def main_window(self):
1746+ return self.select_single(ShellView)
1747+
1748+ @autopilot.logging.log_action(logger.debug)
1749+ def wait_for_greeter_content(self):
1750+ greeter = self.main_window.wait_select_single(objectName='greeter')
1751+ greeter.waiting.wait_for(False)
1752+
1753+ @autopilot.logging.log_action(logger.info)
1754+ def unlock(self):
1755+ greeter = self.main_window.get_greeter()
1756+ if greeter.created:
1757+ greeter_helpers.hide_greeter_with_dbus()
1758+ greeter.created.wait_for(False)
1759+
1760+ def show_dash_from_launcher(self):
1761+ self.main_window.show_dash_from_launcher()
1762+
1763+ def get_number_of_sessions(self):
1764+ application_window = self.select_single('ApplicationWindow')
1765+ return len(application_window.select_many('SessionContainer'))
1766+
1767+ def get_height(self):
1768+ return self.main_window.height
1769+
1770+ def get_width(self):
1771+ return self.main_window.width
1772+
1773+ def ensure_app_loaded(self):
1774+ try:
1775+ indicator = self.select_single('ActivityIndicator')
1776+ indicator.onScreen.wait_for(False)
1777+ except exceptions.StateNotFoundError:
1778+ # This is fine, it's already loaded
1779+ pass
1780+
1781+
1782+class ShellView(ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase):
1783+ """An helper class that makes it easy to interact with the shell"""
1784+
1785+ @classmethod
1786+ def validate_dbus_object(cls, path, state):
1787+ return validate_dbus_object(
1788+ path, state, UNITY8_PATH_ROOT, b'ShellView', title='Unity8')
1789+
1790+ def get_notifications_list(self):
1791+ """Return a list of notifications currently being displayed."""
1792+ return self.select_single(
1793+ Notifications, objectName='notificationList')
1794+
1795+ def get_notifications_panel(self):
1796+ """Return 'Notifications' panel object."""
1797+ return self._get_indicator_panel_item('indicator-messages')
1798+
1799+ def clear_notifications(self):
1800+ """
1801+ Clear all existing notifications from 'Notifications' indicator.
1802+
1803+ """
1804+ if self.is_new_notification_displayed():
1805+ self.open_indicator_page('indicator-messages').clear_all()
1806+ self.close_indicator_page()
1807+
1808+ def open_notifications_indicator(self):
1809+ """Swipe down to display the notifications indicator."""
1810+ return self.open_indicator_page('indicator-messages')
1811+
1812+ def is_new_notification_displayed(self):
1813+ """Return True if new notification message icon is displayed."""
1814+ return self.get_notifications_panel().is_new_message_displayed()
1815+
1816+ def get_passphrase_unlock_screen(self):
1817+ """Wait for input method to be in shown state and return lockscreen."""
1818+ from ubuntu_system_tests.helpers.unity8 import lock_screen
1819+ input_method = self.wait_select_single(
1820+ 'InputMethod', objectName='inputMethod', visible=True)
1821+ input_method.state.wait_for('shown')
1822+ return self.select_single(lock_screen.PassphraseLockscreen)
1823+
1824+ def get_missed_call_snap_decision(self):
1825+ """Return missed call snap decision menu."""
1826+ from ubuntu_system_tests.helpers.snap_decision import missed_call
1827+ return self.select_single(
1828+ missed_call.SnapDecisionMenu, objectName='snapDecision',
1829+ visible=True)
1830+
1831+ def get_phone_stage(self):
1832+ from ubuntu_system_tests.helpers.unity8 import phone_stage
1833+ return self.select_single(phone_stage.PhoneStage, objectName='stage')
1834+
1835+ def swipe_to_show_app_switcher(self):
1836+ """Swipe from right edge to reveal task switcher."""
1837+ stage = self.get_phone_stage()
1838+ stage.swipe_to_top()
1839+ return stage
1840+
1841+ def _is_indicator_panel_opened(self):
1842+ indicator_page = self.wait_select_single('IndicatorsMenu')
1843+ return indicator_page.fullyOpened
1844+
1845+ def is_indicator_item_hidden(self, indicator_name):
1846+ """
1847+ Return bool representing if the requested indicator item is hidden or
1848+ not.
1849+ """
1850+ item = self.select_single('IndicatorItem',
1851+ objectName=indicator_name + '-panelItem')
1852+ return item.hidden
1853+
1854+ def get_greeter(self):
1855+ return self.select_single(greeter_helpers.Greeter)
1856+
1857+ def get_login_loader(self):
1858+ return self.select_single("QQuickLoader", objectName="loginLoader")
1859+
1860+ def get_login_list(self):
1861+ return self.select_single("LoginList")
1862+
1863+ def get_bottombar(self):
1864+ return self.select_single("Bottombar")
1865+
1866+ def get_pinPadLoader(self):
1867+ return self.select_single(
1868+ "QQuickLoader",
1869+ objectName="pinPadLoader"
1870+ )
1871+
1872+ def get_lockscreen(self):
1873+ return self.select_single("Lockscreen")
1874+
1875+ def get_pinentryField(self):
1876+ return self.select_single(objectName="pinentryField")
1877+
1878+ def _get_indicator_panel_item(self, indicator_name):
1879+ return self.select_single(
1880+ 'IndicatorItem',
1881+ objectName=indicator_name+'-panelItem'
1882+ )
1883+
1884+ def _get_indicator_page(self, indicator_name):
1885+ return self.select_single(
1886+ 'IndicatorPage',
1887+ objectName=indicator_name+'-page'
1888+ )
1889+
1890+ @autopilot.logging.log_action(logger.info)
1891+ def open_indicator_page(self, indicator_name):
1892+ """Swipe to open the indicator, wait until it's open.
1893+ :returns: The indicator page.
1894+ """
1895+ widget = self._get_indicator_panel_item(indicator_name)
1896+ start_x, start_y = input.get_center_point(widget)
1897+ end_x = start_x
1898+ end_y = self.height
1899+ self.pointing_device.drag(start_x, start_y, end_x, end_y)
1900+ self.wait_select_single('IndicatorsMenu', fullyOpened=True)
1901+ return self._get_indicator_page(indicator_name)
1902+
1903+ @autopilot.logging.log_action(logger.info)
1904+ def close_indicator_page(self):
1905+ """Swipe to close the opened indicator, wait until it's closed."""
1906+ indicators_menu = self.wait_select_single('IndicatorsMenu')
1907+ end_x, end_y = input.get_center_point(indicators_menu)
1908+ start_x = end_x
1909+ start_y = self.height
1910+ self.pointing_device.drag(start_x, start_y, end_x, end_y)
1911+ indicators_menu.fullyClosed.wait_for(True)
1912+
1913+ @autopilot.logging.log_action(logger.info)
1914+ def show_dash_swiping(self):
1915+ """Show the dash swiping from the left."""
1916+ x, y, width, height = self._get_shell().globalRect
1917+ start_x = x
1918+ end_x = x + width
1919+ start_y = end_y = y + height // 2
1920+
1921+ self.pointing_device.drag(start_x, start_y, end_x, end_y)
1922+ self.get_current_focused_app_id().wait_for('unity8-dash')
1923+
1924+ def _get_shell(self):
1925+ return self.select_single('Shell')
1926+
1927+ def get_current_focused_app_id(self):
1928+ """Return the id of the focused application."""
1929+ return self._get_shell().focusedApplicationId
1930+
1931+ @autopilot.logging.log_action(logger.info)
1932+ def show_dash_from_launcher(self):
1933+ """Open the dash clicking the dash icon on the launcher."""
1934+ launcher = self.open_launcher()
1935+ launcher.click_dash_icon()
1936+ self.get_current_focused_app_id().wait_for('unity8-dash')
1937+ launcher.shown.wait_for(False)
1938+
1939+ @autopilot.logging.log_action(logger.info)
1940+ def open_launcher(self):
1941+ launcher = self._get_launcher()
1942+ launcher.show()
1943+ return launcher
1944+
1945+ def _get_launcher(self):
1946+ return self.select_single(launcher_helpers.Launcher)
1947+
1948+ def is_launcher_open(self):
1949+ return self._get_launcher().shown
1950+
1951+ @autopilot.logging.log_action(logger.info)
1952+ def launch_application(self, application_name):
1953+ """Launch an application.
1954+
1955+ :parameter application_name: The name of the application to launch.
1956+
1957+ """
1958+ launcher = self.open_launcher()
1959+ launcher.click_application_launcher_icon(application_name)
1960+ self.get_current_focused_app_id().wait_for(application_name)
1961+ launcher.shown.wait_for(False)
1962+
1963+ def enter_pin_code(self, code):
1964+ """Enter code 'code' into the single-pin lightdm pincode entry screen.
1965+
1966+ :param code: must be a string of numeric characters.
1967+ :raises: TypeError if code is not a string.
1968+ :raises: ValueError if code contains non-numeric characters.
1969+
1970+ """
1971+ if not isinstance(code, str):
1972+ raise TypeError(
1973+ "'code' parameter must be a string, not %r."
1974+ % type(code)
1975+ )
1976+ for num in code:
1977+ if not num.isdigit():
1978+ raise ValueError(
1979+ "'code' parameter contains non-numeric characters."
1980+ )
1981+ self.pointing_device.click_object(
1982+ self._get_pinpad_button(int(num)))
1983+
1984+ def _get_pinpad_button(self, button_id):
1985+ return self.select_single(
1986+ 'PinPadButton',
1987+ objectName='pinPadButton{}'.format(button_id)
1988+ )
1989+
1990+ def get_shell_orientation_angle(self):
1991+ return self._get_shell().orientationAngle
1992+
1993+ def get_shell_orientation(self):
1994+ return self._get_shell().orientation
1995+
1996+ def get_shell_primary_orientation(self):
1997+ return self._get_shell().primaryOrientation
1998+
1999+ def get_shell_native_orientation(self):
2000+ return self._get_shell().nativeOrientation
2001+
2002+ @autopilot.logging.log_action(logger.info)
2003+ def wait_for_notification(self):
2004+ """Wait for a notification dialog to appear.
2005+
2006+ :return: An object for the notification dialog data.
2007+ :raise StateNotFoundError: if the timeout expires when the
2008+ notification has not appeared.
2009+
2010+ """
2011+ notify_list = self.select_single('Notifications',
2012+ objectName='notificationList')
2013+ visible_notification = notify_list.wait_select_single('Notification',
2014+ visible=True)
2015+ return {'summary': visible_notification.summary,
2016+ 'body': visible_notification.body,
2017+ 'iconSource': visible_notification.iconSource}
2018
2019=== added file 'ubuntu_system_tests/helpers/unity8/shell/fixture_setup.py'
2020--- ubuntu_system_tests/helpers/unity8/shell/fixture_setup.py 1970-01-01 00:00:00 +0000
2021+++ ubuntu_system_tests/helpers/unity8/shell/fixture_setup.py 2016-06-10 02:06:42 +0000
2022@@ -0,0 +1,90 @@
2023+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2024+#
2025+# Unity Autopilot Test Suite
2026+# Copyright (C) 2014 - 2016 Canonical
2027+#
2028+# This program is free software: you can redistribute it and/or modify
2029+# it under the terms of the GNU General Public License as published by
2030+# the Free Software Foundation, either version 3 of the License, or
2031+# (at your option) any later version.
2032+#
2033+# This program is distributed in the hope that it will be useful,
2034+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2035+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2036+# GNU General Public License for more details.
2037+#
2038+# You should have received a copy of the GNU General Public License
2039+# along with this program. If not, see <http://www.gnu.org/licenses/>.
2040+#
2041+
2042+"""Set up and clean up fixtures for the Unity acceptance tests."""
2043+
2044+import fixtures
2045+import os
2046+import subprocess
2047+import sysconfig
2048+
2049+from ubuntu_system_tests.helpers import unity8
2050+
2051+
2052+class FakeScopes(fixtures.Fixture):
2053+
2054+ def setUp(self):
2055+ super().setUp()
2056+ self.useFixture(
2057+ fixtures.EnvironmentVariable(
2058+ 'QML2_IMPORT_PATH',
2059+ newvalue=self._get_fake_scopes_library_path()))
2060+
2061+ def _get_fake_scopes_library_path(self):
2062+ if unity8.running_installed_tests():
2063+ mock_path = 'qml/scopefakes/'
2064+ else:
2065+ mock_path = os.path.join(
2066+ '../lib/', sysconfig.get_config_var('MULTIARCH'),
2067+ 'unity8/qml/scopefakes/')
2068+ lib_path = unity8.get_lib_path()
2069+ ld_library_path = os.path.abspath(os.path.join(lib_path, mock_path))
2070+
2071+ if not os.path.exists(ld_library_path):
2072+ raise RuntimeError(
2073+ 'Expected library path does not exists: %s.' % (
2074+ ld_library_path))
2075+ return ld_library_path
2076+
2077+
2078+class Tutorial(fixtures.Fixture):
2079+
2080+ def __init__(self, enable):
2081+ super().__init__()
2082+ self.enable = enable
2083+
2084+ def setUp(self):
2085+ super().setUp()
2086+ original_state = self._is_tutorial_enabled()
2087+ if self.enable != original_state:
2088+ self.addCleanup(self._set_tutorial, original_state)
2089+ self._set_tutorial(self.enable)
2090+
2091+ def _is_tutorial_enabled(self):
2092+ command = [
2093+ 'dbus-send', '--system', '--print-reply',
2094+ '--dest=org.freedesktop.Accounts',
2095+ '/org/freedesktop/Accounts/User32011',
2096+ 'org.freedesktop.DBus.Properties.Get',
2097+ 'string:com.canonical.unity.AccountsService',
2098+ 'string:demo-edges'
2099+ ]
2100+ output = subprocess.check_output(command, universal_newlines=True)
2101+ return True if output.count('true') else False
2102+
2103+ def _set_tutorial(self, value):
2104+ value_string = 'true' if value else 'false'
2105+ command = [
2106+ 'dbus-send', '--system', '--print-reply',
2107+ '--dest=com.canonical.PropertyService',
2108+ '/com/canonical/PropertyService',
2109+ 'com.canonical.PropertyService.SetProperty',
2110+ 'string:edge', 'boolean:{}'.format(value_string)
2111+ ]
2112+ subprocess.check_output(command)
2113
2114=== added file 'ubuntu_system_tests/helpers/unity8/shell/utils.py'
2115--- ubuntu_system_tests/helpers/unity8/shell/utils.py 1970-01-01 00:00:00 +0000
2116+++ ubuntu_system_tests/helpers/unity8/shell/utils.py 2016-06-10 02:06:42 +0000
2117@@ -0,0 +1,82 @@
2118+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2119+
2120+#
2121+# Ubuntu System Tests
2122+# Copyright (C) 2016 Canonical
2123+#
2124+# This program is free software: you can redistribute it and/or modify
2125+# it under the terms of the GNU General Public License as published by
2126+# the Free Software Foundation, either version 3 of the License, or
2127+# (at your option) any later version.
2128+#
2129+# This program is distributed in the hope that it will be useful,
2130+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2131+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2132+# GNU General Public License for more details.
2133+#
2134+# You should have received a copy of the GNU General Public License
2135+# along with this program. If not, see <http://www.gnu.org/licenses/>.
2136+#
2137+
2138+from functools import wraps
2139+from gi.repository import Notify
2140+import logging
2141+
2142+logger = logging.getLogger(__name__)
2143+
2144+
2145+def disable_qml_mocking(fn):
2146+ """Simple decorator that disables the QML mocks from being loaded."""
2147+ @wraps(fn)
2148+ def wrapper(*args, **kwargs):
2149+ tests_self = args[0]
2150+ tests_self._qml_mock_enabled = False
2151+ return fn(*args, **kwargs)
2152+ return wrapper
2153+
2154+
2155+def create_ephemeral_notification(
2156+ summary='',
2157+ body='',
2158+ icon=None,
2159+ hints=[],
2160+ urgency='NORMAL'
2161+):
2162+ """Create an ephemeral (non-interactive) notification
2163+
2164+ :param summary: Summary text for the notification
2165+ :param body: Body text to display in the notification
2166+ :param icon: Path string to the icon to use
2167+ :param hint_strings: List of tuples containing the 'name' and value
2168+ for setting the hint strings for the notification
2169+ :param urgency: Urgency string for the noticiation, either: 'LOW',
2170+ 'NORMAL', 'CRITICAL'
2171+ """
2172+ Notify.init('Unity8')
2173+
2174+ logger.info(
2175+ "Creating ephemeral: summary(%s), body(%s), urgency(%r) "
2176+ "and Icon(%s)",
2177+ summary,
2178+ body,
2179+ urgency,
2180+ icon
2181+ )
2182+
2183+ notification = Notify.Notification.new(summary, body, icon)
2184+
2185+ for hint in hints:
2186+ key, value = hint
2187+ notification.set_hint_string(key, value)
2188+ logger.info("Adding hint to notification: (%s, %s)", key, value)
2189+ notification.set_urgency(_get_urgency(urgency))
2190+
2191+ return notification
2192+
2193+
2194+def _get_urgency(urgency):
2195+ """Translates urgency string to enum."""
2196+ _urgency_enums = {'LOW': Notify.Urgency.LOW,
2197+ 'NORMAL': Notify.Urgency.NORMAL,
2198+ 'CRITICAL': Notify.Urgency.CRITICAL}
2199+ return _urgency_enums.get(urgency.upper())
2200
2201=== modified file 'ubuntu_system_tests/helpers/unity8/utils.py'
2202--- ubuntu_system_tests/helpers/unity8/utils.py 2016-06-02 11:07:46 +0000
2203+++ ubuntu_system_tests/helpers/unity8/utils.py 2016-06-10 02:06:42 +0000
2204@@ -18,14 +18,19 @@
2205 # along with this program. If not, see <http://www.gnu.org/licenses/>.
2206 #
2207
2208-from ubuntuuitoolkit import UbuntuUIToolkitCustomProxyObjectBase
2209-from unity8 import process_helpers
2210+import os
2211+import subprocess
2212+import sysconfig
2213
2214 from autopilot import introspection
2215+from autopilot.introspection import get_proxy_object_for_existing_process
2216 from autopilot.matchers import Eventually
2217 from testtools.matchers import Equals
2218+from ubuntuuitoolkit import UbuntuUIToolkitCustomProxyObjectBase
2219
2220+from ubuntu_system_tests.helpers.autopilot import patched_select_single
2221 from ubuntu_system_tests.helpers import context
2222+from ubuntu_system_tests.helpers import processes
2223 from ubuntu_system_tests.helpers import timer
2224 from ubuntu_system_tests.helpers.unity8 import greeter
2225
2226@@ -35,33 +40,211 @@
2227 APP_WIN_NAME = 'Scopes'
2228
2229
2230+class CannotAccessUnity(Exception):
2231+ pass
2232+
2233+
2234+class UnityException(Exception):
2235+ """Exception raised when there is an error with the Unity test helpers."""
2236+
2237+
2238+def restart_unity_with_testability(*args):
2239+ """Restarts (or starts) unity with testability enabled.
2240+
2241+ Passes *args arguments to the launched process.
2242+
2243+ """
2244+ args += ("QT_LOAD_TESTABILITY=1",)
2245+ return restart_unity(*args)
2246+
2247+
2248+def restart_unity(*args):
2249+ """Restarts (or starts) unity8 using the provided arguments.
2250+
2251+ Passes *args arguments to the launched process.
2252+
2253+ :raises subprocess.CalledProcessError: if unable to stop or start the
2254+ unity8 upstart job.
2255+
2256+ """
2257+ status = _get_unity_status()
2258+ if "start/" in status:
2259+ processes.stop_job('unity8')
2260+
2261+ pid = processes.start_job('unity8', *args)
2262+ return _get_unity_proxy_object(pid)
2263+
2264+
2265+def _get_unity_status():
2266+ try:
2267+ return processes.get_job_status('unity8')
2268+ except processes.JobError as error:
2269+ raise CannotAccessUnity(str(error))
2270+
2271+
2272+def get_unity_pid():
2273+ try:
2274+ return processes.get_job_pid('unity8')
2275+ except processes.JobError as error:
2276+ raise CannotAccessUnity(str(error))
2277+
2278+
2279+def _get_unity_proxy_object(pid):
2280+ return get_proxy_object_for_existing_process(
2281+ pid=pid,
2282+ emulator_base=UbuntuUIToolkitCustomProxyObjectBase
2283+ )
2284+
2285+
2286+def running_installed_tests():
2287+ binary_path = get_binary_path()
2288+ return binary_path.startswith('/usr')
2289+
2290+
2291+def get_lib_path():
2292+ """Return the library path to use in this test run."""
2293+ if running_installed_tests():
2294+ lib_path = os.path.join(
2295+ "/usr/lib/",
2296+ sysconfig.get_config_var('MULTIARCH'),
2297+ "unity8"
2298+ )
2299+ else:
2300+ binary_path = get_binary_path()
2301+ lib_path = os.path.dirname(binary_path)
2302+ return lib_path
2303+
2304+
2305+def get_default_extra_mock_libraries():
2306+ mocks_path = get_mocks_library_path()
2307+ return os.path.join(mocks_path, 'libusermetrics')
2308+
2309+
2310+def get_mocks_library_path():
2311+ if running_installed_tests():
2312+ mock_path = "qml/mocks/"
2313+ else:
2314+ mock_path = os.path.join(
2315+ "../lib/",
2316+ sysconfig.get_config_var('MULTIARCH'),
2317+ "unity8/qml/mocks/"
2318+ )
2319+ lib_path = get_lib_path()
2320+ ld_library_path = os.path.abspath(
2321+ os.path.join(
2322+ lib_path,
2323+ mock_path,
2324+ )
2325+ )
2326+
2327+ if not os.path.exists(ld_library_path):
2328+ raise RuntimeError(
2329+ "Expected library path does not exists: %s." % (ld_library_path)
2330+ )
2331+ return ld_library_path
2332+
2333+
2334+def get_binary_path(binary="unity8"):
2335+ """Return the path to the specified binary."""
2336+ binary_path = os.path.abspath(
2337+ os.path.join(
2338+ os.path.dirname(__file__),
2339+ "../../../builddir/install/bin/%s" % binary
2340+ )
2341+ )
2342+ if not os.path.exists(binary_path):
2343+ try:
2344+ binary_path = subprocess.check_output(
2345+ ['which', binary],
2346+ universal_newlines=True,
2347+ ).strip()
2348+ except subprocess.CalledProcessError as e:
2349+ raise RuntimeError("Unable to locate %s binary: %r" % (binary, e))
2350+ return binary_path
2351+
2352+
2353+def get_data_dirs(data_dirs_mock_enabled=True):
2354+ """Prepend a mock data path to XDG_DATA_DIRS."""
2355+ data_dirs = _get_xdg_env_path()
2356+ if data_dirs_mock_enabled:
2357+ mock_data_path = _get_full_mock_data_path()
2358+ if os.path.exists(mock_data_path):
2359+ if data_dirs is not None:
2360+ data_dirs = '{0}:{1}'.format(mock_data_path, data_dirs)
2361+ else:
2362+ data_dirs = mock_data_path
2363+ return data_dirs
2364+
2365+
2366+def _get_full_mock_data_path():
2367+ if running_installed_tests():
2368+ data_path = "/usr/share/unity8/mocks/data"
2369+ else:
2370+ data_path = "../../mocks/data"
2371+ return os.path.abspath(
2372+ os.path.join(
2373+ os.path.dirname(__file__),
2374+ data_path
2375+ )
2376+ )
2377+
2378+
2379+def _get_xdg_env_path():
2380+ path = os.getenv("XDG_DATA_DIRS")
2381+ if path is None:
2382+ path = _get_xdg_upstart_env()
2383+ return path
2384+
2385+
2386+def _get_xdg_upstart_env():
2387+ try:
2388+ return subprocess.check_output([
2389+ "/sbin/initctl",
2390+ "get-env",
2391+ "--global",
2392+ "XDG_DATA_DIRS"
2393+ ], universal_newlines=True).rstrip()
2394+ except subprocess.CalledProcessError:
2395+ return None
2396+
2397+
2398+def get_grid_size():
2399+ grid_size = os.getenv('GRID_UNIT_PX')
2400+ if grid_size is None:
2401+ raise RuntimeError(
2402+ "Environment variable GRID_UNIT_PX has not been set."
2403+ )
2404+ return int(grid_size)
2405+
2406+
2407 def ensure_unity_stopped():
2408 if _is_unity8_running():
2409- process_helpers.stop_job('unity8')
2410+ processes.stop_job('unity8')
2411 Eventually(Equals(False), timeout=300).match(_is_unity8_running)
2412
2413
2414 def ensure_unity_running_and_greeter_hidden():
2415 if not _is_unity8_running():
2416- process_helpers.start_job('unity8')
2417+ processes.start_job('unity8')
2418 greeter.wait_for_greeter()
2419
2420 greeter.hide_greeter_with_dbus()
2421
2422
2423 def _is_unity8_running():
2424- return process_helpers.is_job_running('unity8')
2425+ return processes.is_job_running('unity8')
2426
2427
2428 def get_dash():
2429 """Return the Unity8 Dash autopilot custom proxy object."""
2430 from ubuntu_system_tests.helpers.unity8.dash import Dash
2431- pid = process_helpers.get_job_pid('unity8-dash')
2432+ pid = processes.get_job_pid('unity8-dash')
2433 dash_proxy = introspection.get_proxy_object_for_existing_process(
2434 pid=pid,
2435 emulator_base=UbuntuUIToolkitCustomProxyObjectBase,
2436 )
2437- return dash_proxy.select_single(Dash)
2438+ return patched_select_single(root=dash_proxy, class_object=Dash,
2439+ class_name='Dash')
2440
2441
2442 def launch_application_from_launcher(app_name):
2443@@ -104,4 +287,4 @@
2444 app_names = stage.get_app_window_names()
2445 for app_name in app_names:
2446 if not app_name == APP_WIN_NAME:
2447- close_app(app_name)
2448+ pass
2449
2450=== modified file 'ubuntu_system_tests/selftests/test_tests_to_run.py'
2451--- ubuntu_system_tests/selftests/test_tests_to_run.py 2016-06-06 09:53:20 +0000
2452+++ ubuntu_system_tests/selftests/test_tests_to_run.py 2016-06-10 02:06:42 +0000
2453@@ -133,7 +133,7 @@
2454 'ubuntu_system_tests.helpers.unity8.utils.greeter',
2455 new_callable=FakeGreeterHelpers)
2456 @mock.patch(
2457- 'ubuntu_system_tests.helpers.unity8.utils.process_helpers',
2458+ 'ubuntu_system_tests.helpers.unity8.utils.processes',
2459 new_callable=FakeProcessHelpers)
2460 class EnsureUnityInRequiredStateTestCase(unittest.TestCase):
2461
2462
2463=== modified file 'ubuntu_system_tests/tests/base.py'
2464--- ubuntu_system_tests/tests/base.py 2016-05-16 17:05:42 +0000
2465+++ ubuntu_system_tests/tests/base.py 2016-06-10 02:06:42 +0000
2466@@ -26,30 +26,28 @@
2467 from tempfile import mkstemp
2468 from threading import Event
2469
2470+import autopilot
2471 from autopilot import (
2472 exceptions,
2473 input,
2474- logging as autopilot_logging,
2475 testcase
2476 )
2477 from autopilot._fixtures import OSKAlwaysEnabled
2478 from autopilot.introspection import _object_registry as object_registry
2479 from ubuntuuitoolkit import fixture_setup
2480-from unity8 import process_helpers
2481
2482-from ubuntu_system_tests.helpers import autopilot
2483+from ubuntu_system_tests.helpers.autopilot import get_job_proxy_object
2484 from ubuntu_system_tests.helpers import context
2485 from ubuntu_system_tests.helpers import images
2486 from ubuntu_system_tests.helpers import mir
2487 from ubuntu_system_tests.helpers.notifications import sim_pin_observer
2488 from ubuntu_system_tests.helpers import ofono
2489-from ubuntu_system_tests.helpers.processes import wait_for_job_spawned
2490+from ubuntu_system_tests.helpers import processes
2491 from ubuntu_system_tests.helpers import screen
2492 from ubuntu_system_tests.helpers.timeout import timeout
2493 from ubuntu_system_tests.helpers import unity8
2494-from ubuntu_system_tests.helpers.unity8 import get_dash
2495-from ubuntu_system_tests.helpers.unity8 import sensors
2496-from ubuntu_system_tests.helpers.unity8.shell import Unity8 # NOQA
2497+from ubuntu_system_tests.helpers.unity8 import get_dash, sensors
2498+from ubuntu_system_tests.helpers.unity8.shell._cpo import Unity8 # NOQA
2499 from ubuntu_system_tests.helpers import wait_until
2500 from ubuntu_system_tests.helpers import webapp
2501
2502@@ -84,9 +82,9 @@
2503 context.shared.retry_time = 10000
2504
2505 def _get_unity8_proxy_object(self):
2506- return autopilot.get_job_proxy_object('unity8')
2507+ return get_job_proxy_object('unity8')
2508
2509- @autopilot_logging.log_action(logger.info)
2510+ @autopilot.logging.log_action(logger.info)
2511 def launch_unity(self, fake_sensors=False, dismiss_sim_unlock=True):
2512 """Launch Unity8 with testability enabled.
2513
2514@@ -149,11 +147,11 @@
2515 args = ['QT_LOAD_TESTABILITY=1']
2516 if no_wait:
2517 args.append('--no-wait')
2518- process_helpers.start_job(unity8.PROC_NAME, *args)
2519+ processes.start_job(unity8.PROC_NAME, *args)
2520 if no_wait:
2521 # just wait for job to be spawned rather than fully running
2522- wait_for_job_spawned(unity8.PROC_NAME)
2523- context.shared.unity_pid = process_helpers._get_unity_pid()
2524+ processes.wait_for_job_spawned(unity8.PROC_NAME)
2525+ context.shared.unity_pid = unity8.get_unity_pid()
2526
2527 def _enable_osk_for_uitk(self):
2528 """Enable use of the OSK with uitk helpers."""
2529@@ -216,7 +214,7 @@
2530 isinstance(exception, DBusException) or
2531 isinstance(exception, TimeoutError) or
2532 isinstance(exception, exceptions.BackendException)))
2533- @autopilot_logging.log_action(logger.info)
2534+ @autopilot.logging.log_action(logger.info)
2535 def restart_unity(self, fake_sensors=False):
2536 """
2537 Restart and unlock unity8
2538
2539=== modified file 'ubuntu_system_tests/tests/test_tutorial.py'
2540--- ubuntu_system_tests/tests/test_tutorial.py 2015-05-21 18:15:40 +0000
2541+++ ubuntu_system_tests/tests/test_tutorial.py 2016-06-10 02:06:42 +0000
2542@@ -21,12 +21,8 @@
2543 from autopilot.matchers import Eventually
2544 from testtools.matchers import Equals
2545
2546-from unity8.shell import fixture_setup
2547-
2548-# unused import to load the tutorial custom proxy objects.
2549-from unity8.shell.emulators import tutorial # NOQA
2550-
2551 from ubuntu_system_tests.tests import base
2552+from ubuntu_system_tests.helpers.unity8.shell import fixture_setup
2553
2554
2555 class TutorialTestCase(base.BaseUbuntuSystemTestCase):
2556
2557=== modified file 'ubuntu_system_tests/tests/test_with_dialer.py'
2558--- ubuntu_system_tests/tests/test_with_dialer.py 2016-02-03 22:25:18 +0000
2559+++ ubuntu_system_tests/tests/test_with_dialer.py 2016-06-10 02:06:42 +0000
2560@@ -20,9 +20,9 @@
2561 from autopilot.matchers import Eventually
2562 from testtools.matchers import Equals
2563
2564-from unity8 import process_helpers as unity_helpers
2565-
2566 from ubuntu_system_tests.helpers import dialer_app
2567+from ubuntu_system_tests.helpers.unity8 import greeter
2568+
2569 from ubuntu_system_tests.tests import base
2570
2571
2572@@ -44,8 +44,8 @@
2573 self.assertThat(self.dialer_app.contacts_page.active,
2574 Eventually(Equals(True)))
2575
2576- unity_helpers.lock_unity()
2577- unity_helpers.unlock_unity()
2578+ greeter.lock_unity()
2579+ greeter.unlock_unity()
2580
2581 self.assertThat(self.dialer_app.contacts_page.active,
2582 Eventually(Equals(True)))

Subscribers

People subscribed via source and target branches

to all changes: