on xenial help sign in
Added a test to swipe out an application started by url-dispatcher.
commit711c6936a27c7d26f1b7c3c2cde606ba62a9ea5b authorLeo Arias <leo.arias@canonical.com> dateWed 12 Feb 2014, 15:13 (13 years ago) parentd42832d21d558e
9 files changed+211−75
debian/control+2 tests/autopilot/unity8/__init__.py+16−12 tests/autopilot/unity8/application_lifecycle/tests/test_application_lifecycle.py+9−13 tests/autopilot/unity8/application_lifecycle/tests/test_url_dispatcher.py+116 tests/autopilot/unity8/process_helpers.py+9−7 tests/autopilot/unity8/shell/emulators/main_window.py+45−27 tests/autopilot/unity8/shell/tests/__init__.py+8−6 tests/autopilot/unity8/shell/tests/test_hud.py+4−7 tests/autopilot/unity8/shell/tests/test_notifications.py+2−3
debian/control+2
@@ -111,8 +111,10 @@ Depends: gir1.2-glib-2.0,
111111 python-fixtures,
112112 python-gi,
113113 python-mock,
114+ ubuntu-ui-toolkit-autopilot,
114115 unity8 (>= ${source:Version}),
115116 unity8-fake-env (>= ${source:Version}),
117+ url-dispatcher-tools,
116118 ${misc:Depends},
117119 ${python:Depends},
118120 ${shlibs:Depends},
tests/autopilot/unity8/__init__.py+16−12
@@ -1,7 +1,7 @@
11# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
22#
33# Unity Autopilot Test Suite
4−# Copyright (C) 2012-2013 Canonical
4+# Copyright (C) 2012, 2013, 2014 Canonical
55#
66# This program is free software: you can redistribute it and/or modify
77# it under the terms of the GNU General Public License as published by
@@ -88,28 +88,31 @@ def get_binary_path(binary="unity8"):
8888 return binary_path
8989
9090
91−def get_data_dirs():
91+def get_data_dirs(data_dirs_mock_enabled=True):
9292 """Prepend a mock data path to XDG_DATA_DIRS."""
93+ data_dirs = _get_xdg_env_path()
94+ if data_dirs_mock_enabled:
95+ mock_data_path = _get_full_mock_data_path()
96+ if os.path.exists(mock_data_path):
97+ if data_dirs is not None:
98+ data_dirs = '{0}:{1}'.format(mock_data_path, data_dirs)
99+ else:
100+ data_dirs = mock_data_path
101+ return data_dirs
102+
103+
104+def _get_full_mock_data_path():
93105 if running_installed_tests():
94106 data_path = "/usr/share/unity8/mocks/data"
95107 else:
96108 data_path = "../../mocks/data"
97− full_data_path = os.path.abspath(
109+ return os.path.abspath(
98110 os.path.join(
99111 os.path.dirname(__file__),
100112 data_path
101113 )
102114 )
103115
104− if os.path.exists(full_data_path):
105− xdg_path = _get_xdg_env_path()
106− if xdg_path is not None:
107− return "{0}:{1}".format(full_data_path, xdg_path)
108− else:
109− return full_data_path
110− else:
111− return None
112−
113116
114117def _get_xdg_env_path():
115118 path = os.getenv("XDG_DATA_DIRS")
@@ -129,6 +132,7 @@ def _get_xdg_upstart_env():
129132 except subprocess.CalledProcessError:
130133 return None
131134
135+
132136def get_grid_size():
133137 grid_size = os.getenv('GRID_UNIT_PX')
134138 if grid_size is None:
tests/autopilot/unity8/application_lifecycle/tests/test_application_lifecycle.py+9−13
@@ -1,7 +1,7 @@
11# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
22#
33# Unity Autopilot Test Suite
4−# Copyright (C) 2013 Canonical
4+# Copyright (C) 2013, 2014 Canonical
55#
66# This program is free software: you can redistribute it and/or modify
77# it under the terms of the GNU General Public License as published by
@@ -44,9 +44,8 @@ class ApplicationLifecycleTests(UnityTestCase):
4444 self.skipTest("Test cannot be run on the desktop.")
4545
4646 def swipe_screen_from_right(self):
47− qml_view = self.main_window.get_qml_view()
48− width = qml_view.width
49− height = qml_view.height
47+ width = self.main_window.width
48+ height = self.main_window.height
5049 start_x = width
5150 start_y = int(height/2)
5251 end_x = int(width/2)
@@ -55,9 +54,6 @@ class ApplicationLifecycleTests(UnityTestCase):
5554 logger.info("Swiping screen from the right edge")
5655 self.touch.drag(start_x, start_y, end_x, end_y)
5756
58− def _get_current_focused_app_id(self):
59− return self._proxy.select_single("Shell").currentFocusedAppId
60−
6157 def _launch_app(self, app_name):
6258 """Launches the application *app_name*
6359
@@ -86,7 +82,7 @@ class ApplicationLifecycleTests(UnityTestCase):
8682
8783 self.assertThat(app, NotEquals(None))
8884 self.assertThat(
89− self._get_current_focused_app_id(),
85+ self.main_window.get_current_focused_app_id(),
9086 Eventually(Equals("messaging-app"))
9187 )
9288
@@ -98,13 +94,13 @@ class ApplicationLifecycleTests(UnityTestCase):
9894
9995 self._launch_app("messaging-app")
10096 self.assertThat(
101− self._get_current_focused_app_id(),
97+ self.main_window.get_current_focused_app_id(),
10298 Eventually(Equals("messaging-app"))
10399 )
104100
105101 self._launch_app("address-book-app")
106102 self.assertThat(
107− self._get_current_focused_app_id(),
103+ self.main_window.get_current_focused_app_id(),
108104 Eventually(Equals("address-book-app"))
109105 )
110106
@@ -119,19 +115,19 @@ class ApplicationLifecycleTests(UnityTestCase):
119115
120116 self._launch_app("messaging-app")
121117 self.assertThat(
122− self._get_current_focused_app_id(),
118+ self.main_window.get_current_focused_app_id(),
123119 Eventually(Equals("messaging-app"))
124120 )
125121
126122 self._launch_app("address-book-app")
127123 self.assertThat(
128− self._get_current_focused_app_id(),
124+ self.main_window.get_current_focused_app_id(),
129125 Eventually(Equals("address-book-app"))
130126 )
131127
132128 self.swipe_screen_from_right()
133129
134130 self.assertThat(
135− self._get_current_focused_app_id(),
131+ self.main_window.get_current_focused_app_id(),
136132 Eventually(Equals("messaging-app"))
137133 )
tests/autopilot/unity8/application_lifecycle/tests/test_url_dispatcher.pynew file+116
@@ -0,0 +1,116 @@
1+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2+#
3+# Unity Autopilot Test Suite
4+# Copyright (C) 2014 Canonical
5+#
6+# This program is free software: you can redistribute it and/or modify
7+# it under the terms of the GNU General Public License as published by
8+# the Free Software Foundation, either version 3 of the License, or
9+# (at your option) any later version.
10+#
11+# This program is distributed in the hope that it will be useful,
12+# but WITHOUT ANY WARRANTY; without even the implied warranty of
13+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+# GNU General Public License for more details.
15+#
16+# You should have received a copy of the GNU General Public License
17+# along with this program. If not, see <http://www.gnu.org/licenses/>.
18+#
19+
20+"""Test the integration with the URL dispatcher service."""
21+
22+import os
23+import tempfile
24+
25+from autopilot import platform
26+from autopilot.matchers import Eventually
27+from testtools.matchers import Equals
28+from ubuntuuitoolkit import base as toolkit_base
29+
30+from unity8 import process_helpers
31+from unity8.shell import tests
32+
33+
34+class URLDispatcherTestCase(tests.UnityTestCase):
35+
36+ scenarios = tests._get_device_emulation_scenarios()
37+
38+ test_qml = ("""
39+import QtQuick 2.0
40+import Ubuntu.Components 0.1
41+
42+MainView {
43+ width: units.gu(48)
44+ height: units.gu(60)
45+
46+ Label {
47+ text: 'Test application.'
48+ }
49+}
50+""")
51+
52+ desktop_file_contents = ("""[Desktop Entry]
53+Type=Application
54+Name=test
55+Exec={qmlscene} {qml_file_path}
56+Icon=Not important
57+""")
58+
59+ def setUp(self):
60+ if platform.model() == 'Desktop':
61+ self.skipTest("URL dispatcher doesn't work on the desktop.")
62+ super(URLDispatcherTestCase, self).setUp()
63+ self._qml_mock_enabled = False
64+ self._data_dirs_mock_enabled = False
65+ unity_proxy = self.launch_unity()
66+ process_helpers.unlock_unity(unity_proxy)
67+
68+ def create_test_application(self):
69+ # FIXME most of this code is duplicated in the toolkit. We should
70+ # create a fixture on the toolkit for other projects to use.
71+ # http://pad.lv/1277334 --elopio - 2014-02-06
72+ qml_file_path = self._write_test_qml_file()
73+ self.addCleanup(os.remove, qml_file_path)
74+ desktop_file_path = self._write_test_desktop_file(qml_file_path)
75+ self.addCleanup(os.remove, desktop_file_path)
76+ return qml_file_path, desktop_file_path
77+
78+ def _write_test_qml_file(self):
79+ qml_file = tempfile.NamedTemporaryFile(suffix='.qml', delete=False)
80+ qml_file.write(self.test_qml.encode('utf-8'))
81+ qml_file.close()
82+ return qml_file.name
83+
84+ def _write_test_desktop_file(self, qml_file_path):
85+ desktop_file_dir = self._get_local_desktop_file_directory()
86+ if not os.path.exists(desktop_file_dir):
87+ os.makedirs(desktop_file_dir)
88+ desktop_file = tempfile.NamedTemporaryFile(
89+ suffix='.desktop', dir=desktop_file_dir, delete=False)
90+ contents = self.desktop_file_contents.format(
91+ qmlscene=toolkit_base.get_qmlscene_launch_command(),
92+ qml_file_path=qml_file_path)
93+ desktop_file.write(contents.encode('utf-8'))
94+ desktop_file.close()
95+ return desktop_file.name
96+
97+ def _get_local_desktop_file_directory(self):
98+ return os.path.join(
99+ os.environ.get('HOME'), '.local', 'share', 'applications')
100+
101+ def test_swipe_out_application_started_by_url_dispatcher(self):
102+ _, desktop_file_path = self.create_test_application()
103+ desktop_file_name = os.path.basename(desktop_file_path)
104+ application_name, _ = os.path.splitext(desktop_file_name)
105+
106+ self.assertEqual('', self.main_window.get_current_focused_app_id())
107+ self.addCleanup(os.system, 'pkill qmlscene')
108+ os.system('url-dispatcher application:///{}'.format(desktop_file_name))
109+ self.assertThat(
110+ self.main_window.get_current_focused_app_id,
111+ Eventually(Equals(application_name)))
112+
113+ self.main_window.show_dash_swiping()
114+ self.assertThat(
115+ self.main_window.get_current_focused_app_id,
116+ Eventually(Equals('')))
tests/autopilot/unity8/process_helpers.py+9−7
@@ -1,7 +1,7 @@
11# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
22#
33# Unity Autopilot Utilities
4−# Copyright (C) 2013 Canonical
4+# Copyright (C) 2013, 2014 Canonical
55#
66# This program is free software: you can redistribute it and/or modify
77# it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@ from autopilot.introspection import (
2323)
2424import logging
2525import subprocess
26−from unity8.shell.emulators import UnityEmulatorBase
27−from unity8.shell.emulators.main_window import MainWindow
26+from unity8.shell import emulators
27+from unity8.shell.emulators import main_window as main_window_emulator
2828
2929logger = logging.getLogger(__name__)
3030
@@ -54,7 +54,7 @@ def unlock_unity(unity_proxy_obj=None):
5454 try:
5555 pid = _get_unity_pid()
5656 unity = _get_unity_proxy_object(pid)
57− main_window = MainWindow(unity)
57+ main_window = unity.select_single(main_window_emulator.QQuickView)
5858 except ProcessSearchError as e:
5959 raise CannotAccessUnity(
6060 "Cannot introspect unity, make sure that it has been started "
@@ -64,7 +64,8 @@ def unlock_unity(unity_proxy_obj=None):
6464 % str(e)
6565 )
6666 else:
67− main_window = MainWindow(unity_proxy_obj)
67+ main_window = unity_proxy_obj.select_single(
68+ main_window_emulator.QQuickView)
6869
6970 greeter = main_window.get_greeter()
7071 if greeter.created == False:
@@ -110,7 +111,8 @@ def restart_unity(*args):
110111 status = _get_unity_status()
111112 if "start/" in status:
112113 try:
113− output = subprocess.check_output(['/sbin/initctl', 'stop', 'unity8'])
114+ output = subprocess.check_output(
115+ ['/sbin/initctl', 'stop', 'unity8'])
114116 logger.info(output)
115117 except subprocess.CalledProcessError as e:
116118 e.args += (
@@ -155,5 +157,5 @@ def _get_unity_pid():
155157def _get_unity_proxy_object(pid):
156158 return get_proxy_object_for_existing_process(
157159 pid=pid,
158− emulator_base=UnityEmulatorBase,
160+ emulator_base=emulators.UnityEmulatorBase,
159161 )
tests/autopilot/unity8/shell/emulators/main_window.py+45−27
@@ -1,7 +1,7 @@
11# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
22#
33# Unity Autopilot Test Suite
4−# Copyright (C) 2012-2013 Canonical
4+# Copyright (C) 2012, 2013, 2014 Canonical
55#
66# This program is free software: you can redistribute it and/or modify
77# it under the terms of the GNU General Public License as published by
@@ -17,85 +17,103 @@
1717# along with this program. If not, see <http://www.gnu.org/licenses/>.
1818#
1919
20+import logging
2021
22+from autopilot import logging as autopilot_logging
23+
24+from unity8.shell import emulators
2125from unity8.shell.emulators.greeter import Greeter
2226from unity8.shell.emulators.hud import Hud
2327from unity8.shell.emulators.dash import Dash
2428from unity8.shell.emulators.launcher import Launcher
2529
30+logger = logging.getLogger(__name__)
2631
27−class MainWindow(object):
28− """An emulator class that makes it easy to interact with the shell"""
29−
30− def __init__(self, app):
31− self.app = app
3232
33− def get_qml_view(self):
34− """Get the main QML view"""
35− return self.app.select_single("QQuickView")
33+class QQuickView(emulators.UnityEmulatorBase):
34+ """An emulator class that makes it easy to interact with the shell"""
3635
3736 def get_greeter(self):
38− return self.app.select_single(Greeter)
37+ return self.select_single(Greeter)
3938
4039 def get_greeter_content_loader(self):
41− return self.app.wait_select_single(
40+ return self.wait_select_single(
4241 "QQuickLoader",
4342 objectName="greeterContentLoader"
4443 )
4544
4645 def get_greeter_background(self):
47− return self.app.select_single("CrossFadeImage", objectName="greeterBackground")
46+ return self.select_single(
47+ "CrossFadeImage", objectName="greeterBackground")
4848
4949 def get_login_loader(self):
50− return self.app.select_single("QQuickLoader", objectName="loginLoader")
50+ return self.select_single("QQuickLoader", objectName="loginLoader")
5151
5252 def get_login_list(self):
53− return self.app.select_single("LoginList")
53+ return self.select_single("LoginList")
5454
5555 def get_hud(self):
56− return self.app.select_single(Hud)
56+ return self.select_single(Hud)
5757
5858 def get_hud_showable(self):
59− return self.app.select_single("Showable", objectName="hudShowable")
59+ return self.select_single("Showable", objectName="hudShowable")
6060
6161 def get_hud_show_button(self):
62− return self.app.select_single("HudButton")
62+ return self.select_single("HudButton")
6363
6464 def get_hud_edge_drag_area(self):
65− return self.app.select_single(objectName="hudDragArea")
65+ return self.select_single(objectName="hudDragArea")
6666
6767 def get_dash(self):
68− return self.app.select_single(Dash)
68+ return self.select_single(Dash)
6969
7070 def get_bottombar(self):
71− return self.app.select_single("Bottombar")
71+ return self.select_single("Bottombar")
7272
7373 def get_launcher(self):
74− return self.app.select_single(Launcher)
74+ return self.select_single(Launcher)
7575
7676 def get_pinPadLoader(self):
77− return self.app.select_single(
77+ return self.select_single(
7878 "QQuickLoader",
7979 objectName="pinPadLoader"
8080 )
8181
8282 def get_pinPadButton(self, buttonId):
83− return self.app.select_single(
83+ return self.select_single(
8484 "PinPadButton",
8585 objectName="pinPadButton%i" % buttonId
8686 )
8787
8888 def get_lockscreen(self):
89− return self.app.select_single("Lockscreen")
89+ return self.select_single("Lockscreen")
9090
9191 def get_pinentryField(self):
92− return self.app.select_single(objectName="pinentryField")
92+ return self.select_single(objectName="pinentryField")
9393
9494 def get_indicator(self, indicator_name):
95− return self.app.wait_select_single(
95+ return self.wait_select_single(
9696 'DefaultIndicatorWidget',
9797 objectName=indicator_name+'-widget'
9898 )
9999
100100 def get_shell_background(self):
101− return self.app.select_single("CrossFadeImage", objectName="backgroundImage")
101+ return self.select_single(
102+ "CrossFadeImage", objectName="backgroundImage")
103+
104+ @autopilot_logging.log_action(logger.info)
105+ def show_dash_swiping(self):
106+ """Show the dash swiping from the left."""
107+ width = self.width
108+ height = self.height
109+ start_x = 0
110+ start_y = height // 2
111+ end_x = width
112+ end_y = start_y
113+
114+ self.pointing_device.drag(start_x, start_y, end_x, end_y)
115+ return self.get_dash()
116+
117+ def get_current_focused_app_id(self):
118+ """Return the id of the focused application."""
119+ return self.select_single('Shell').currentFocusedAppId
tests/autopilot/unity8/shell/tests/__init__.py+8−6
@@ -1,7 +1,7 @@
11# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
22#
33# Unity Autopilot Test Suite
4−# Copyright (C) 2012-2013 Canonical
4+# Copyright (C) 2012, 2013, 2014 Canonical
55#
66# This program is free software: you can redistribute it and/or modify
77# it under the terms of the GNU General Public License as published by
@@ -43,8 +43,8 @@ from unity8 import (
4343 get_data_dirs
4444)
4545from unity8.process_helpers import restart_unity_with_testability
46+from unity8.shell.emulators import main_window as main_window_emulator
4647from unity8.shell.emulators.dash import Dash
47−from unity8.shell.emulators.main_window import MainWindow
4848
4949
5050logger = logging.getLogger(__name__)
@@ -139,10 +139,9 @@ class UnityTestCase(AutopilotTestCase):
139139 self._proxy = None
140140 self._lightdm_mock_type = None
141141 self._qml_mock_enabled = True
142+ self._data_dirs_mock_enabled = True
142143 self._environment = {}
143144
144− self._patch_data_dirs()
145−
146145 #### FIXME: This is a work around re: lp:1238417 ####
147146 if model() != "Desktop":
148147 from autopilot.input import _uinput
@@ -268,6 +267,9 @@ class UnityTestCase(AutopilotTestCase):
268267 if self._qml_mock_enabled:
269268 self._setup_extra_mock_environment_patch()
270269
270+ if self._data_dirs_mock_enabled:
271+ self._patch_data_dirs()
272+
271273 # FIXME: we shouldn't be doing this
272274 # $MIR_SOCKET, fallback to $XDG_RUNTIME_DIR/mir_socket and
273275 # /tmp/mir_socket as last resort
@@ -321,7 +323,7 @@ class UnityTestCase(AutopilotTestCase):
321323 logger.warning("Appears unity was already stopped!")
322324
323325 def _patch_data_dirs(self):
324− data_dirs = get_data_dirs()
326+ data_dirs = get_data_dirs(self._data_dirs_mock_enabled)
325327 if data_dirs is not None:
326328 self._environment['XDG_DATA_DIRS'] = data_dirs
327329
@@ -391,4 +393,4 @@ class UnityTestCase(AutopilotTestCase):
391393
392394 @property
393395 def main_window(self):
394− return MainWindow(self._proxy)
396+ return self._proxy.select_single(main_window_emulator.QQuickView)
tests/autopilot/unity8/shell/tests/test_hud.py+4−7
@@ -1,7 +1,7 @@
11# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
22#
33# Unity Autopilot Test Suite
4−# Copyright (C) 2012-2013 Canonical
4+# Copyright (C) 2012, 2013, 2014 Canonical
55#
66# This program is free software: you can redistribute it and/or modify
77# it under the terms of the GNU General Public License as published by
@@ -41,7 +41,6 @@ class TestHud(UnityTestCase, DragMixin):
4141 """
4242 unity_proxy = self.launch_unity()
4343 unlock_unity(unity_proxy)
44− window = self.main_window.get_qml_view()
4544 hud_show_button = self.main_window.get_hud_show_button()
4645 edge_drag_area = self.main_window.get_hud_edge_drag_area()
4746 hud = self.main_window.get_hud()
@@ -49,7 +48,7 @@ class TestHud(UnityTestCase, DragMixin):
4948 self._launch_test_app_from_app_screen()
5049
5150 swipe_coords = hud.get_button_swipe_coords(
52− window,
51+ self.main_window,
5352 hud_show_button
5453 )
5554 initialBottomMargin = int(hud_show_button.bottomMargin)
@@ -83,14 +82,13 @@ class TestHud(UnityTestCase, DragMixin):
8382 """
8483 unity_proxy = self.launch_unity()
8584 unlock_unity(unity_proxy)
86− window = self.main_window.get_qml_view()
8785 hud_show_button = self.main_window.get_hud_show_button()
8886 hud = self.main_window.get_hud()
8987
9088 self._launch_test_app_from_app_screen()
9189
9290 swipe_coords = hud.get_button_swipe_coords(
93− window,
91+ self.main_window,
9492 hud_show_button
9593 )
9694
@@ -137,7 +135,6 @@ class TestHud(UnityTestCase, DragMixin):
137135 """
138136 unity_proxy = self.launch_unity()
139137 unlock_unity(unity_proxy)
140− window = self.main_window.get_qml_view()
141138 hud = self.main_window.get_hud()
142139
143140 self._launch_test_app_from_app_screen()
@@ -146,7 +143,7 @@ class TestHud(UnityTestCase, DragMixin):
146143
147144 start_x, start_y = hud.get_close_button_coords()
148145 end_x = start_x
149− end_y = int(window.height / 2)
146+ end_y = int(self.main_window.height / 2)
150147
151148 self.touch.drag(start_x, start_y, end_x, end_y)
152149 self.assertThat(hud.shown, Eventually(Equals(False)))
tests/autopilot/unity8/shell/tests/test_notifications.py+2−3
@@ -1,7 +1,7 @@
11# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
22#
33# Unity Autopilot Test Suite
4−# Copyright (C) 2012-2013 Canonical
4+# Copyright (C) 2012, 2013, 2014 Canonical
55#
66# This program is free software: you can redistribute it and/or modify
77# it under the terms of the GNU General Public License as published by
@@ -61,8 +61,7 @@ class NotificationsBase(UnityTestCase):
6161 return os.path.dirname(__file__) + "/../../../../../qml/graphics/" + icon_name
6262
6363 def _get_notifications_list(self):
64− main_view = self.main_window.get_qml_view()
65− return main_view.select_single(
64+ return self.main_window.select_single(
6665 "Notifications",
6766 objectName='notificationList'
6867 )