Merge lp:~vrruiz/gallery-app/test-share-photo into lp:gallery-app

Proposed by Víctor R. Ruiz
Status: Superseded
Proposed branch: lp:~vrruiz/gallery-app/test-share-photo
Merge into: lp:gallery-app
Diff against target: 284 lines (+242/-0)
4 files modified
debian/control (+2/-0)
tests/autopilot/gallery_app/credentials.py (+117/-0)
tests/autopilot/gallery_app/emulators/photo_viewer.py (+18/-0)
tests/autopilot/gallery_app/tests/test_share.py (+105/-0)
To merge this branch: bzr merge lp:~vrruiz/gallery-app/test-share-photo
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Needs Fixing
Leo Arias (community) code review Needs Fixing
Ubuntu Phablet Team Pending
Review via email: mp+225947@code.launchpad.net

This proposal has been superseded by a proposal from 2014-07-16.

Commit message

Autopilot: Test for share photo.

Description of the change

Autopilot: Test for share photo.

To post a comment you must log in.
Revision history for this message
Víctor R. Ruiz (vrruiz) wrote :

Work in progress (there is a problem with Friends and python-dbusmock).

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1006. By Víctor R. Ruiz

Autopilot: Fix dbus object names

1007. By Víctor R. Ruiz

Autopilot: Create fake Facebook account to share photos

Revision history for this message
Víctor R. Ruiz (vrruiz) wrote :

Ready for review.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1008. By Víctor R. Ruiz

Dependency for autopilot tests - python3-dbusmock

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

202 + def post_button(self):
214 + def do_share_photo(self):
206 + def share_panel(self):

These shouldn't be part of the test case. They should be custom proxy objects or used in methods of the parent custom proxy object.

43 +class AccountManager(object):
159 +class FakeFriendsService(object):

Please talk with Richard and Brendan. They are working with the devs to move a fake dbus service like this one to the right project. In their case URLDispatcher, in your case the friends service. We agreed that it's ok to duplicate the code in the project like you are doing here just if we are working at the same time to put it in the right place. Maybe one of them can help you talking with your devs to see how easy would it be to get this done in the right way.

254 + sleep(5)

You should use Eventually instead of a sleep.

249 + def test_facebook(self):

You need a better name for this test. Something like test_share_with_facebook_must_call_friends_service.

Finally, all your FIXMEs look really weird. I don't understand how you are creating the account without starting the main loop, as it's asynchronous. It seems though that you don't need to store any credentials, just create the account. That's really nice, you can probably remove a lot of the code in Account Manager. If you can get mardy to help you with this it would be great. If not, maybe I can give you a hand later on the week.

Thanks Victor. This test is great.

review: Needs Fixing (code review)
1009. By Víctor R. Ruiz

Autopilot: test_share refactor

1010. By Víctor R. Ruiz

Missing dependency

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

Unmerged revisions

1010. By Víctor R. Ruiz

Missing dependency

1009. By Víctor R. Ruiz

Autopilot: test_share refactor

1008. By Víctor R. Ruiz

Dependency for autopilot tests - python3-dbusmock

1007. By Víctor R. Ruiz

Autopilot: Create fake Facebook account to share photos

1006. By Víctor R. Ruiz

Autopilot: Fix dbus object names

1005. By Víctor R. Ruiz

Autopilot: Move UI code to helper function

1004. By Víctor R. Ruiz

Autopilot: Fix dbus path

1003. By Víctor R. Ruiz

Fix typos

1002. By Víctor R. Ruiz

Autopilot: Test for share photo

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 2014-05-09 16:08:13 +0000
3+++ debian/control 2014-07-16 11:37:08 +0000
4@@ -51,6 +51,8 @@
5 unity8-autopilot,
6 python3-pkg-resources,
7 python3-autopilot,
8+ python3-dbusmock,
9+ python3-fixtures,
10 Description: Autopilot tests for the photo gallery for Ubuntu
11 gallery-app is a photo gallery for the Ubuntu platform. This package contains
12 autopilot tests for it.
13
14=== added file 'tests/autopilot/gallery_app/credentials.py'
15--- tests/autopilot/gallery_app/credentials.py 1970-01-01 00:00:00 +0000
16+++ tests/autopilot/gallery_app/credentials.py 2014-07-16 11:37:08 +0000
17@@ -0,0 +1,117 @@
18+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
19+#
20+# Copyright (C) 2014 Canonical Ltd.
21+#
22+# This program is free software; you can redistribute it and/or modify
23+# it under the terms of the GNU General Public License version 3, as published
24+# by the Free Software Foundation.
25+#
26+# This program is distributed in the hope that it will be useful,
27+# but WITHOUT ANY WARRANTY; without even the implied warranty of
28+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29+# GNU General Public License for more details.
30+#
31+# You should have received a copy of the GNU General Public License
32+# along with this program. If not, see <http://www.gnu.org/licenses/>.
33+
34+
35+import threading
36+
37+from gi.repository import Accounts, GLib, Signon
38+
39+
40+class CredentialsException(Exception):
41+ """Exception for credentials problems."""
42+
43+
44+class AccountManager(object):
45+
46+ def __init__(self):
47+ self._manager = Accounts.Manager()
48+
49+ def _start_main_loop(self):
50+ self.error = None
51+ self._main_loop = GLib.MainLoop()
52+ self._main_loop_thread = threading.Thread(
53+ target=self._main_loop.run)
54+ self._main_loop_thread.start()
55+
56+ def _join_main_loop(self):
57+ self._main_loop_thread.join()
58+ if self.error is not None:
59+ raise CredentialsException(self.error.message)
60+
61+ def add_credentials(self, user_name, password):
62+ ## FIXME: If enabled, the application gets hanged
63+ # self._start_main_loop()
64+
65+ account = self._create_fb_account()
66+
67+ ## FIXME: If enabled, this code returns a ref count error
68+ # info = self._get_identity_info(user_name, password)
69+ # identity = Signon.Identity.new()
70+ # identity.store_credentials_with_info(
71+ # info, self._set_credentials_id_to_account, account)
72+
73+ ## FIXME: If enabled, the application gets hanged
74+ # self._join_main_loop()
75+ return account
76+
77+ def _create_fb_account(self):
78+ account = self._manager.create_account('facebook')
79+ account.set_enabled(True)
80+ account.store(self._on_account_created, None)
81+ return account
82+
83+ def _on_account_created(self, account, error, _):
84+ if error:
85+ self.error = error
86+ self._main_loop.quit()
87+
88+ def _get_identity_info(self, user_name, password):
89+ info = Signon.IdentityInfo.new()
90+ info.set_username(user_name)
91+ info.set_caption(user_name)
92+ info.set_secret(password, True)
93+ return info
94+
95+ def _set_credentials_id_to_account(self, identity, id, error, account):
96+ if error:
97+ self.error = error
98+ self._main_loop.quit()
99+
100+ account.set_variant('CredentialsId', GLib.Variant('u', id))
101+ account.store(self._process_session, None)
102+
103+ def _process_session(self, account, error, _):
104+ if error:
105+ self.error = error
106+ self._main_loop.quit()
107+
108+ account_service = Accounts.AccountService.new(account, None)
109+ auth_data = account_service.get_auth_data()
110+ identity = auth_data.get_credentials_id()
111+ method = auth_data.get_method()
112+ mechanism = auth_data.get_mechanism()
113+ session_data = auth_data.get_parameters()
114+ session = Signon.AuthSession.new(identity, method)
115+ session.process(
116+ session_data, mechanism, self._on_login_processed, None)
117+
118+ def _on_login_processed(self, session, reply, error, userdata):
119+ if error:
120+ self.error = error
121+
122+ self._main_loop.quit()
123+
124+ def delete_account(self, account):
125+ self._start_main_loop()
126+ account.delete()
127+ account.store(self._on_account_deleted, None)
128+ self._join_main_loop()
129+
130+ def _on_account_deleted(self, account, error, userdata):
131+ if error:
132+ self.error = error
133+
134+ self._main_loop.quit()
135
136=== modified file 'tests/autopilot/gallery_app/emulators/photo_viewer.py'
137--- tests/autopilot/gallery_app/emulators/photo_viewer.py 2014-06-20 15:25:14 +0000
138+++ tests/autopilot/gallery_app/emulators/photo_viewer.py 2014-07-16 11:37:08 +0000
139@@ -6,6 +6,7 @@
140 # by the Free Software Foundation.
141
142 from gallery_app.emulators.gallery_utils import GalleryUtils
143+from gallery_app.emulators.main_screen import MainScreen
144
145
146 class PhotoViewer(GalleryUtils):
147@@ -123,6 +124,12 @@
148 return self.app.wait_select_single("EditPreview",
149 objectName="editPreview")
150
151+ def get_post_button(self):
152+ return self.app.wait_select_single(objectName="postButton")
153+
154+ def get_share_panel(self):
155+ return self.app.wait_select_single(objectName="shareComponent")
156+
157 def _click_item(self, item):
158 self.pointing_device.click_object(item)
159
160@@ -149,3 +156,14 @@
161 def click_enhance_item(self):
162 enhance_item = self.get_auto_enhance_menu_item()
163 self._click_item(enhance_item)
164+
165+ def do_share_photo(self):
166+ """Click on a photo and share it"""
167+ # Tab on share button
168+ main_view = self.app.select_single(MainScreen)
169+ main_view.open_toolbar().click_button("shareButton")
170+ # Ensure that the share panel is opened
171+ self.get_share_panel()
172+ post_button = self.get_post_button()
173+ # Click on "Post" button to upload image to Facebook fake service
174+ self.pointing_device.click_object(post_button)
175
176=== added file 'tests/autopilot/gallery_app/tests/test_share.py'
177--- tests/autopilot/gallery_app/tests/test_share.py 1970-01-01 00:00:00 +0000
178+++ tests/autopilot/gallery_app/tests/test_share.py 2014-07-16 11:37:08 +0000
179@@ -0,0 +1,105 @@
180+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
181+# Copyright 2013 Canonical
182+#
183+# This program is free software: you can redistribute it and/or modify it
184+# under the terms of the GNU General Public License version 3, as published
185+# by the Free Software Foundation.
186+
187+"""Tests the Photos share options of the gallery app."""
188+
189+import dbus
190+import dbusmock
191+import fixtures
192+
193+from time import sleep
194+from testtools.matchers import Equals, GreaterThan
195+
196+from gallery_app import credentials
197+from gallery_app.tests.test_photo_viewer import TestPhotoViewerBase
198+
199+
200+class FakeFriendsService(object):
201+ """Fake Friends service"""
202+
203+ def __init__(self, dbus_connection):
204+ super(FakeFriendsService, self).__init__()
205+ self.dbus_connection = dbus_connection
206+ self.mock = self._get_mock_interface()
207+ self._add_methods()
208+
209+ def get_calls(self):
210+ return self.mock.GetCalls()
211+
212+ def _add_methods(self):
213+ self.mock.AddMethod(
214+ 'com.canonical.Friends.Dispatcher',
215+ 'Upload',
216+ 'sss',
217+ 's',
218+ 'ret = "https://www.facebook.com/649348222_10152546147613223"'
219+ )
220+
221+ def _get_mock_interface(self):
222+ return dbus.Interface(
223+ self.dbus_connection.get_object(
224+ 'com.canonical.Friends.Dispatcher',
225+ '/com/canonical/friends/Dispatcher',
226+ ),
227+ dbusmock.MOCK_IFACE)
228+
229+
230+class FakeFriendsServiceFixture(fixtures.Fixture, dbusmock.DBusTestCase):
231+ """Fixture for the Fake Friends Service"""
232+
233+ def setUp(self):
234+ super(FakeFriendsServiceFixture, self).setUp()
235+ self._use_fake_friends_service()
236+
237+ def _use_fake_friends_service(self):
238+ """Starts a fake Friends service"""
239+ self._spawn_fake_friends_service()
240+ dbus_connection = self.get_dbus(system_bus=False)
241+ self.fake_friends_service = FakeFriendsService(dbus_connection)
242+
243+ def _spawn_fake_friends_service(self):
244+ self.friends_service_mock = self.spawn_server(
245+ 'com.canonical.Friends.Dispatcher',
246+ '/com/canonical/friends/Dispatcher',
247+ 'com.canonical.Friends.Dispatcher',
248+ system_bus=False,
249+ )
250+ self.addCleanup(self._terminate_process)
251+
252+ def _terminate_process(self):
253+ """Finish the fake Friends service"""
254+ self.friends_service_mock.terminate()
255+ self.friends_service_mock.wait()
256+
257+
258+class ShareTestCase(TestPhotoViewerBase):
259+ """Test Facebook share"""
260+
261+ def setUp(self):
262+ # Create Facebook account
263+ self._create_account()
264+ # Use the fake friends service
265+ self.friends_service_fixture = FakeFriendsServiceFixture()
266+ self.useFixture(self.friends_service_fixture)
267+ super(ShareTestCase, self).setUp()
268+
269+ def _create_account(self):
270+ """Creates a fake Facebook account in Online Accounts"""
271+ account_manager = credentials.AccountManager()
272+ account = account_manager.add_credentials('dummy@example.com', '****')
273+ self.addCleanup(account_manager.delete_account, account)
274+
275+ def test_share_photo_to_facebook(self):
276+ """Test share photo to Facebook"""
277+ # Click on a photo and share it
278+ self.photo_viewer.do_share_photo()
279+ # Wait a little bit
280+ sleep(5)
281+ # Check that the call to fake service was correctly done
282+ calls = self.friends_service_fixture.fake_friends_service.get_calls()
283+ self.assertThat(len(calls), GreaterThan(0))
284+ self.assertThat(calls[0][1], Equals('Upload'))

Subscribers

People subscribed via source and target branches