on xenial help sign in
Added autopilot helpers for the app scope and the app preview.
f812445Leo Arias
debian/control+1
@@ -102,6 +102,7 @@ Depends: gir1.2-glib-2.0,
102 libqt5test5,
102 libqt5test5,
103 libqt5widgets5,
103 libqt5widgets5,
104 python-evdev,
104 python-evdev,
105+ python-fixtures,
105 python-gi,
106 python-gi,
106 python-mock,
107 python-mock,
107 unity8 (>= ${source:Version}),
108 unity8 (>= ${source:Version}),
debian/unity8-fake-env.install+1
@@ -1,2 +1,3 @@
1usr/lib/*/unity8/qml/mocks
1usr/lib/*/unity8/qml/mocks
2+usr/lib/*/unity8/qml/scopefakes
2usr/share/unity8/mocks
3usr/share/unity8/mocks
qml/Dash/Apps/AppPreview.qml+1
@@ -97,6 +97,7 @@ GenericPreview {
97 spacing: units.gu(1)
97 spacing: units.gu(1)
98
98
99 Label {
99 Label {
100+ objectName: "descriptionLabel"
100 anchors { left: parent.left; right: parent.right }
101 anchors { left: parent.left; right: parent.right }
101 text: root.previewData.description
102 text: root.previewData.description
102 fontSize: "medium"
103 fontSize: "medium"
tests/autopilot/unity8/shell/emulators/__init__.py+1−1
@@ -25,7 +25,7 @@ class UnityEmulatorBase(introspection.CustomEmulatorBase):
25
25
26 def __init__(self, *args):
26 def __init__(self, *args):
27 super(UnityEmulatorBase, self).__init__(*args)
27 super(UnityEmulatorBase, self).__init__(*args)
28− self.pointing_device = input.Touch.create()
28+ self.pointing_device = input.Pointer(device=input.Touch.create())
29
29
30
30
31class UnityEmulatorException(Exception):
31class UnityEmulatorException(Exception):
tests/autopilot/unity8/shell/emulators/dash.py+53−2
@@ -138,8 +138,59 @@ class Dash(emulators.UnityEmulatorBase):
138
138
139
139
140class GenericScopeView(emulators.UnityEmulatorBase):
140class GenericScopeView(emulators.UnityEmulatorBase):
141− """Autopilot emulators for generic scopes."""
141+ """Autopilot emulator for generic scopes."""
142
142
143
143
144class DashApps(emulators.UnityEmulatorBase):
144class DashApps(emulators.UnityEmulatorBase):
145− """Autopilot emulators for the applications scope."""
145+ """Autopilot emulator for the applications scope."""
146+
147+ def get_applications(self, category):
148+ """Return the list of applications on a category.
149+
150+ :parameter category: The name of the category.
151+
152+ """
153+ category_element = self._get_category_element(category)
154+ application_tiles = category_element.select_many('Tile')
155+ # TODO return them on the same order they are displayed.
156+ # --elopio - 2014-1-15
157+ return [tile.text for tile in application_tiles]
158+
159+ def _get_category_element(self, category):
160+ try:
161+ return self.select_single(
162+ 'Base', objectName='dashCategory{}'.format(category))
163+ except dbus.StateNotFoundError:
164+ raise emulators.UnityEmulatorException(
165+ 'No category found with name {}'.format(category))
166+
167+ @autopilot_logging.log_action(logger.info)
168+ def open_preview(self, category, app_name):
169+ """Open the preview of an application.
170+
171+ :parameter category: The name of the category where the application is.
172+ :app_name: The name of the application.
173+
174+ """
175+ category_element = self._get_category_element(category)
176+ icon = category_element.select_single('Tile', text=app_name)
177+ # FIXME some categories need a long press in order to see the preview.
178+ # Some categories do not show previews, like recent apps.
179+ # --elopio - 2014-1-14
180+ self.pointing_device.click_object(icon)
181+ return self.get_root_instance().wait_select_single(AppPreview)
182+
183+
184+class AppPreview(emulators.UnityEmulatorBase):
185+ """Autopilot emulator for the application preview."""
186+
187+ def get_details(self):
188+ """Return the details of the application showed in its preview."""
189+ title = self.select_single('Label', objectName='titleLabel').text
190+ publisher = self.select_single(
191+ 'Label', objectName='subtitleLabel').text
192+ description = self.select_single(
193+ 'Label', objectName='descriptionLabel').text
194+ # TODO return screenshots, icon, rating and reviews.
195+ # --elopio - 2014-1-15
196+ return dict(title=title, publisher=publisher, description=description)
tests/autopilot/unity8/shell/tests/test_emulators.py+89−2
@@ -17,23 +17,43 @@
17# along with this program. If not, see <http://www.gnu.org/licenses/>.
17# along with this program. If not, see <http://www.gnu.org/licenses/>.
18#
18#
19
19
20+"""Tests for the Dash autopilot emulators.
21+
22+The autopilot emulators are helpers for tests that check a user journey that
23+involves the dash. The code for some of those tests will not be inside this
24+branch, but in projects that depend on unity or that test the whole system
25+integration. So, we need to test the helpers in order to make sure that we
26+don't break them for those external projects.
27+
28+"""
29+
30+import os
31+import sysconfig
32+
20import mock
33import mock
21
34
35+import fixtures
36+from testtools.matchers import Contains, HasLength
37+
38+import unity8
22from unity8 import process_helpers
39from unity8 import process_helpers
23from unity8.shell import emulators, tests
40from unity8.shell import emulators, tests
24from unity8.shell.emulators import dash as dash_emulators
41from unity8.shell.emulators import dash as dash_emulators
25
42
26
43
27−class DashEmulatorTestCase(tests.UnityTestCase):
44+class DashBaseTestCase(tests.UnityTestCase):
28
45
29 scenarios = tests._get_device_emulation_scenarios()
46 scenarios = tests._get_device_emulation_scenarios()
30
47
31 def setUp(self):
48 def setUp(self):
32− super(DashEmulatorTestCase, self).setUp()
49+ super(DashBaseTestCase, self).setUp()
33 unity_proxy = self.launch_unity()
50 unity_proxy = self.launch_unity()
34 process_helpers.unlock_unity(unity_proxy)
51 process_helpers.unlock_unity(unity_proxy)
35 self.dash = self.main_window.get_dash()
52 self.dash = self.main_window.get_dash()
36
53
54+
55+class DashEmulatorTestCase(DashBaseTestCase):
56+
37 def test_open_unexisting_scope(self):
57 def test_open_unexisting_scope(self):
38 scope_name = 'unexisting'
58 scope_name = 'unexisting'
39 with mock.patch.object(self.dash, 'pointing_device') as mock_pointer:
59 with mock.patch.object(self.dash, 'pointing_device') as mock_pointer:
@@ -118,3 +138,70 @@ class DashEmulatorTestCase(tests.UnityTestCase):
118 scope = self.dash.open_scope(self._get_scope_name_from_id(scope_id))
138 scope = self.dash.open_scope(self._get_scope_name_from_id(scope_id))
119 self._assert_scope_is_opened(scope, scope_id)
139 self._assert_scope_is_opened(scope, scope_id)
120 self.assertIsInstance(scope, dash_emulators.DashApps)
140 self.assertIsInstance(scope, dash_emulators.DashApps)
141+
142+
143+class DashAppsEmulatorTestCase(DashBaseTestCase):
144+
145+ available_applications = [
146+ 'Title.1', 'Title.21', 'Title.41', 'Title.61', 'Title.81',
147+ 'Title.101', 'Title.121', 'Title.141', 'Title.161', 'Title.181',
148+ 'Title.201', 'Title.221', 'Title.241', 'Title.261', 'Title.281']
149+
150+ def setUp(self):
151+ self._use_scope_fakes()
152+ super(DashAppsEmulatorTestCase, self).setUp()
153+ self.applications_scope = self.dash.open_scope('applications')
154+
155+ def _use_scope_fakes(self):
156+ self.useFixture(
157+ fixtures.EnvironmentVariable(
158+ 'QML2_IMPORT_PATH',
159+ newvalue=self._get_fake_scopes_library_path()))
160+
161+ def _get_fake_scopes_library_path(self):
162+ if unity8.running_installed_tests():
163+ mock_path = 'qml/scopefakes/'
164+ else:
165+ mock_path = os.path.join(
166+ '../lib/', sysconfig.get_config_var('MULTIARCH'),
167+ 'unity8/qml/scopefakes/')
168+ lib_path = unity8.get_lib_path()
169+ ld_library_path = os.path.abspath(os.path.join(lib_path, mock_path))
170+
171+ if not os.path.exists(ld_library_path):
172+ raise RuntimeError(
173+ 'Expected library path does not exists: %s.' % (
174+ ld_library_path))
175+ return ld_library_path
176+
177+ def test_get_applications_with_unexisting_category(self):
178+ exception = self.assertRaises(
179+ emulators.UnityEmulatorException,
180+ self.applications_scope.get_applications,
181+ 'unexisting category')
182+
183+ self.assertEqual(
184+ 'No category found with name unexisting category', str(exception))
185+
186+ def test_get_applications_should_return_list_with_names(self):
187+ category = 'installed'
188+ expected_apps_count = self._get_number_of_application_slots(category)
189+ expected_applications = self.available_applications[
190+ :expected_apps_count]
191+
192+ applications = self.applications_scope.get_applications(category)
193+
194+ self.assertThat(applications, HasLength(expected_apps_count))
195+ for expected in expected_applications:
196+ self.assertThat(applications, Contains(expected))
197+
198+ def _get_number_of_application_slots(self, category):
199+ category_element = self.applications_scope._get_category_element(
200+ category)
201+ grid = category_element.select_single('GenericFilterGrid')
202+ return grid.columns * grid.rows
203+
204+ def test_open_preview(self):
205+ preview = self.applications_scope.open_preview('installed', 'Title.1')
206+ self.assertIsInstance(preview, dash_emulators.AppPreview)
207+ self.assertTrue(preview.isCurrent)
tests/mocks/Unity/CMakeLists.txt+9−2
@@ -1,5 +1,7 @@
1add_subdirectory(Application)
1add_subdirectory(Application)
2add_subdirectory(Indicators)
2add_subdirectory(Indicators)
3+add_subdirectory(Launcher)
4+add_subdirectory(Notifications)
3
5
4pkg_search_module(DEE dee-1.0 REQUIRED)
6pkg_search_module(DEE dee-1.0 REQUIRED)
5pkg_search_module(GOBJECT gobject-2.0 REQUIRED)
7pkg_search_module(GOBJECT gobject-2.0 REQUIRED)
@@ -41,5 +43,10 @@ file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/qmldir"
41 DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
43 DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
42 )
44 )
43
45
44−add_subdirectory(Launcher)
46+install(TARGETS FakeUnityQml
45−add_subdirectory(Notifications)
47+ DESTINATION ${SHELL_INSTALL_QML}/scopefakes/Unity
48+ )
49+
50+install(FILES qmldir
51+ DESTINATION ${SHELL_INSTALL_QML}/scopefakes/Unity
52+ )
tests/mocks/Unity/fake_applications_scope.cpp+2−1
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013, 2014 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
5 * it under the terms of the GNU General Public License as published by
@@ -30,6 +30,7 @@ ApplicationsScope::ApplicationsScope(bool visible, QObject* parent)
30 m_id = "applications.scope";
30 m_id = "applications.scope";
31 m_name = "Applications";
31 m_name = "Applications";
32 m_visible = visible;
32 m_visible = visible;
33+ m_previewRendererName = "preview-application";
33 m_categories->setModel(createCategoriesModel());
34 m_categories->setModel(createCategoriesModel());
34}
35}
35
36
tests/mocks/Unity/fake_preview.cpp+5−3
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013, 2014 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
5 * it under the terms of the GNU General Public License as published by
@@ -16,13 +16,15 @@
16
16
17#include "fake_preview.h"
17#include "fake_preview.h"
18
18
19−Preview::Preview(QObject *parent): QObject(parent)
19+Preview::Preview(const QString &rendererName, QObject *parent):
20+ QObject(parent),
21+ m_rendererName(rendererName)
20{
22{
21}
23}
22
24
23QString Preview::rendererName() const
25QString Preview::rendererName() const
24{
26{
25− return "generic-preview";
27+ return m_rendererName;
26}
28}
27
29
28QString Preview::title() const
30QString Preview::title() const
tests/mocks/Unity/fake_preview.h+5−2
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013, 2014 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
5 * it under the terms of the GNU General Public License as published by
@@ -38,7 +38,7 @@ class Q_DECL_EXPORT Preview : public QObject
38 Q_PROPERTY(QString image READ image NOTIFY previewChanged)
38 Q_PROPERTY(QString image READ image NOTIFY previewChanged)
39
39
40public:
40public:
41− explicit Preview(QObject *parent = 0);
41+ explicit Preview(const QString &rendererName, QObject *parent = 0);
42
42
43 QString rendererName() const;
43 QString rendererName() const;
44 QString title() const;
44 QString title() const;
@@ -55,6 +55,9 @@ public:
55
55
56Q_SIGNALS:
56Q_SIGNALS:
57 void previewChanged();
57 void previewChanged();
58+
59+private:
60+ QString m_rendererName;
58};
61};
59
62
60Q_DECLARE_METATYPE(Preview *)
63Q_DECLARE_METATYPE(Preview *)
tests/mocks/Unity/fake_scope.cpp+3−2
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013, 2014 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
5 * it under the terms of the GNU General Public License as published by
@@ -38,6 +38,7 @@ Scope::Scope(QString const& id, QString const& name, bool visible, QObject* pare
38 , m_isActive(false)
38 , m_isActive(false)
39 , m_categories(new Categories(this))
39 , m_categories(new Categories(this))
40 , m_results(new DeeListModel(this))
40 , m_results(new DeeListModel(this))
41+ , m_previewRendererName("preview-generic")
41{
42{
42 DeeModel* results_model = create_results_model(20, 300);
43 DeeModel* results_model = create_results_model(20, 300);
43 m_categories->setResultModel(results_model);
44 m_categories->setResultModel(results_model);
@@ -47,7 +48,7 @@ Scope::Scope(QString const& id, QString const& name, bool visible, QObject* pare
47 m_timer.setInterval(1000);
48 m_timer.setInterval(1000);
48 m_timer.setSingleShot(true);
49 m_timer.setSingleShot(true);
49 connect(&m_timer, &QTimer::timeout, [this]() {
50 connect(&m_timer, &QTimer::timeout, [this]() {
50− Preview *p = new Preview(this);
51+ Preview *p = new Preview(m_previewRendererName, this);
51 Q_EMIT previewReady(p);
52 Q_EMIT previewReady(p);
52 });
53 });
53}
54}
tests/mocks/Unity/fake_scope.h+3−1
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013, 2014 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
5 * it under the terms of the GNU General Public License as published by
@@ -116,6 +116,8 @@ protected:
116 bool m_searching;
116 bool m_searching;
117 bool m_isActive;
117 bool m_isActive;
118
118
119+ QString m_previewRendererName;
120+
119 Categories* m_categories;
121 Categories* m_categories;
120 DeeListModel* m_results;
122 DeeListModel* m_results;
121
123