Merge lp:~om26er/address-book-app/abook_navigation_favorites into lp:address-book-app

Proposed by Omer Akram
Status: Work in progress
Proposed branch: lp:~om26er/address-book-app/abook_navigation_favorites
Merge into: lp:address-book-app
Prerequisite: lp:~renatofilho/address-book-app/new-favorite-list
Diff against target: 726 lines (+446/-35)
15 files modified
src/imports/ContactView/ContactDetailFavoriteView.qml (+1/-0)
src/imports/Ubuntu/Contacts/ContactListView.qml (+2/-0)
tests/autopilot/address_book_app/emulators/__init__.py (+12/-0)
tests/autopilot/address_book_app/emulators/contact_list_page.py (+145/-26)
tests/autopilot/address_book_app/emulators/contact_view.py (+57/-0)
tests/autopilot/address_book_app/emulators/main_window.py (+27/-3)
tests/autopilot/address_book_app/helpers.py (+74/-0)
tests/autopilot/address_book_app/tests/__init__.py (+17/-6)
tests/autopilot/address_book_app/tests/test_add_contact.py (+4/-0)
tests/autopilot/address_book_app/tests/test_contactlist.py (+4/-0)
tests/autopilot/address_book_app/tests/test_delete_contact.py (+1/-0)
tests/autopilot/address_book_app/tests/test_edit_contact.py (+4/-0)
tests/autopilot/address_book_app/tests/test_favorites.py (+96/-0)
tests/autopilot/address_book_app/tests/test_multiple_pick_mode.py (+1/-0)
tests/autopilot/address_book_app/tests/test_single_pick_mode.py (+1/-0)
To merge this branch: bzr merge lp:~om26er/address-book-app/abook_navigation_favorites
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Needs Fixing
Allan LeSage Pending
Ubuntu Phablet Team Pending
Review via email: mp+211431@code.launchpad.net

This proposal supersedes a proposal from 2014-03-17.

Commit message

autopilot: add tests for favoriting contacts, using the new dummy backend service

Description of the change

Note: I only fixed the code to use the dummy backend service, no other changes are from me.

Depends on lp:~renatofilho/address-book-service/dummy-mode to be merged.

To post a comment you must log in.
163. By Omer Akram

remove syncevolution dep

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:163
http://jenkins.qa.ubuntu.com/job/address-book-app-ci/455/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/address-book-app-trusty-amd64-ci/165
    SUCCESS: http://jenkins.qa.ubuntu.com/job/address-book-app-trusty-armhf-ci/165
        deb: http://jenkins.qa.ubuntu.com/job/address-book-app-trusty-armhf-ci/165/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/address-book-app-trusty-i386-ci/165
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty/4001
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty-touch/3586/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-trusty/3493
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/4042
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/4042/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/3588
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/3588/artifact/work/output/*zip*/output.zip
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-runner-mako/5918/console
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/4891

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/address-book-app-ci/455/rebuild

review: Needs Fixing (continuous-integration)
164. By Omer Akram

remove unused test code, fix things

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:164
http://jenkins.qa.ubuntu.com/job/address-book-app-ci/456/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/address-book-app-trusty-amd64-ci/166
    SUCCESS: http://jenkins.qa.ubuntu.com/job/address-book-app-trusty-armhf-ci/166
        deb: http://jenkins.qa.ubuntu.com/job/address-book-app-trusty-armhf-ci/166/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/address-book-app-trusty-i386-ci/166
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty/4005
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty-touch/3590/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-trusty/3495
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/4046
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/4046/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/3592
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/3592/artifact/work/output/*zip*/output.zip
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-runner-mako/5922/console
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/4895

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/address-book-app-ci/456/rebuild

review: Needs Fixing (continuous-integration)
165. By Omer Akram

make dummy backend code reusable by other test cases

166. By Omer Akram

add docstrings for new tests

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:165
http://jenkins.qa.ubuntu.com/job/address-book-app-ci/458/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/address-book-app-trusty-amd64-ci/168
    SUCCESS: http://jenkins.qa.ubuntu.com/job/address-book-app-trusty-armhf-ci/168
        deb: http://jenkins.qa.ubuntu.com/job/address-book-app-trusty-armhf-ci/168/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/address-book-app-trusty-i386-ci/168
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty/4016
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty-touch/3601/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-trusty/3507
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/4057
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/4057/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/3603
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/3603/artifact/work/output/*zip*/output.zip
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-runner-mako/5932/console
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/4907

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/address-book-app-ci/458/rebuild

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

FAILED: Continuous integration, rev:166
http://jenkins.qa.ubuntu.com/job/address-book-app-ci/460/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/address-book-app-trusty-amd64-ci/170
    SUCCESS: http://jenkins.qa.ubuntu.com/job/address-book-app-trusty-armhf-ci/170
        deb: http://jenkins.qa.ubuntu.com/job/address-book-app-trusty-armhf-ci/170/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/address-book-app-trusty-i386-ci/170
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty/4021
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty-touch/3606/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-trusty/3512
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/4062
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/4062/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/3608
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/3608/artifact/work/output/*zip*/output.zip
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-runner-mako/5937/console
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/4912

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/address-book-app-ci/460/rebuild

review: Needs Fixing (continuous-integration)
167. By Omer Akram

make starting of dummy backend a reusable helper for other apps to consume

168. By Omer Akram

adapt autopilot tests to UI changes in trunk

169. By Omer Akram

merge trunk

Unmerged revisions

169. By Omer Akram

merge trunk

168. By Omer Akram

adapt autopilot tests to UI changes in trunk

167. By Omer Akram

make starting of dummy backend a reusable helper for other apps to consume

166. By Omer Akram

add docstrings for new tests

165. By Omer Akram

make dummy backend code reusable by other test cases

164. By Omer Akram

remove unused test code, fix things

163. By Omer Akram

remove syncevolution dep

162. By Omer Akram

fix pep8 and pyflakes warnings for test_favorite, did not touch other modules

161. By Omer Akram

remove unused test code

160. By Omer Akram

don't use memory backend for favorite tests, use the new dummy backend from the service

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/imports/ContactView/ContactDetailFavoriteView.qml'
2--- src/imports/ContactView/ContactDetailFavoriteView.qml 2014-02-25 21:52:58 +0000
3+++ src/imports/ContactView/ContactDetailFavoriteView.qml 2014-03-26 22:14:30 +0000
4@@ -28,6 +28,7 @@
5
6 Icon {
7 id: icon
8+ objectName: 'favoriteIcon'
9
10 anchors.fill: parent
11 name: root.detail && root.detail.favorite ? "favorite-selected" : "favorite-unselected"
12
13=== modified file 'src/imports/Ubuntu/Contacts/ContactListView.qml'
14--- src/imports/Ubuntu/Contacts/ContactListView.qml 2014-02-25 20:20:21 +0000
15+++ src/imports/Ubuntu/Contacts/ContactListView.qml 2014-03-26 22:14:30 +0000
16@@ -57,6 +57,7 @@
17 anchors.fill: parent
18 Label {
19 id: lblAll
20+ objectName: "labelAll"
21
22 anchors {
23 top: parent.top
24@@ -84,6 +85,7 @@
25
26 Label {
27 id: lblFavourites
28+ objectName: "labelFavorite"
29
30 anchors {
31 top: parent.top
32
33=== modified file 'tests/autopilot/address_book_app/emulators/__init__.py'
34--- tests/autopilot/address_book_app/emulators/__init__.py 2013-07-09 18:42:30 +0000
35+++ tests/autopilot/address_book_app/emulators/__init__.py 2014-03-26 22:14:30 +0000
36@@ -4,3 +4,15 @@
37 # This program is free software: you can redistribute it and/or modify it
38 # under the terms of the GNU General Public License version 3, as published
39 # by the Free Software Foundation.
40+
41+
42+def get_nearest_parent_matching_type(child, desired_type):
43+ """Climb down the widget tree, return first instance of desired_type"""
44+ while type(child).__name__ != desired_type:
45+ parent = child.get_parent()
46+ if type(child).__name__ == 'AddressBookApp':
47+ # we reached the root and found nothing
48+ return None
49+ else:
50+ child = parent
51+ return child
52
53=== modified file 'tests/autopilot/address_book_app/emulators/contact_list_page.py'
54--- tests/autopilot/address_book_app/emulators/contact_list_page.py 2014-02-13 16:44:12 +0000
55+++ tests/autopilot/address_book_app/emulators/contact_list_page.py 2014-03-26 22:14:30 +0000
56@@ -1,20 +1,24 @@
57 # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
58-
59-""" ContactListPage emulator for Addressbook App tests """
60-
61 # Copyright 2014 Canonical
62 #
63 # This program is free software: you can redistribute it and/or modify it
64 # under the terms of the GNU General Public License version 3, as published
65 # by the Free Software Foundation.
66
67+""" ContactListPage emulator for Addressbook App tests """
68+
69 import logging
70+from time import sleep
71
72+from autopilot import logging as autopilot_logging
73 from autopilot.introspection.dbus import StateNotFoundError
74+from autopilot.matchers import Eventually
75+from testtools.matchers import GreaterThan
76 from ubuntuuitoolkit import emulators as uitk
77
78-LOGGER = logging.getLogger(__name__)
79-from time import sleep
80+from address_book_app.emulators import get_nearest_parent_matching_type
81+
82+logger = logging.getLogger(__name__)
83
84
85 class ContactListPage(uitk.UbuntuUIToolkitEmulatorBase):
86@@ -27,9 +31,12 @@
87 super(ContactListPage, self).__init__(*args)
88
89 def get_contacts(self):
90- """
91- Returns a list of ContactDelegate objects and populate
92- self.selection_marks
93+ """Returns a list of ContactDelegate objects.
94+
95+ Also populate self.selection_marks.
96+
97+ :return: The list of ContactDelegate objects.
98+
99 """
100 sleep(1)
101 self.contacts = self.select_many("ContactDelegate")
102@@ -41,10 +48,12 @@
103 self.selection_marks.append(mark)
104 return self.contacts
105
106+ @autopilot_logging.log_action(logger.info)
107 def select_contacts_by_index(self, indices):
108- """ Select contacts corresponding to the list of index in indices
109-
110- :param indices: List of integers
111+ """Select contacts corresponding to the list of index in indices.
112+
113+ :param indices: List of integer indices of contacts to select.
114+
115 """
116 self.deselect_all()
117
118@@ -53,8 +62,9 @@
119 self.selected_marks.append(self.selection_marks[idx])
120 self.pointing_device.click_object(self.selection_marks[idx])
121
122+ @autopilot_logging.log_action(logger.info)
123 def deselect_all(self):
124- """Deselect every contacts"""
125+ """Deselect every contact."""
126 contacts = self.select_many("ContactDelegate")
127 self.selected_marks = []
128 for contact in contacts:
129@@ -63,28 +73,137 @@
130 objectName="selectionMark")
131 self.pointing_device.click_object(mark)
132
133+ @autopilot_logging.log_action(logger.info)
134 def click_button(self, objectname):
135 """Press a button that matches objectname
136
137- :param objectname: Name of the object
138+ :param objectname: The name of the object.
139+ :raise StateNotFoundError: When a matching button is not found.
140+
141 """
142- try:
143- buttons = self.select_many("Button",
144- objectName=objectname)
145- for button in buttons:
146- if button.visible:
147- self.pointing_device.click_object(button)
148- except StateNotFoundError:
149- LOGGER.error(
150- 'Button with objectName "{0}" not found.'.format(objectname)
151- )
152- raise
153+ button = self.select_single("Button",
154+ objectName=objectname,
155+ visible=True)
156+ self.pointing_device.click_object(button)
157
158+ @autopilot_logging.log_action(logger.info)
159 def cancel(self):
160- """Press the cancel button displayed when pick mode is enabled"""
161+ """Press the cancel button displayed when pick mode is enabled."""
162 self.click_button("DialogButtons.rejectButton")
163
164+ @autopilot_logging.log_action(logger.info)
165 def delete(self):
166- """Press the delete button displayed when pick mode is enabled"""
167+ """Press the delete button displayed when pick mode is enabled."""
168 self.click_button("DialogButtons.acceptButton")
169 self.get_contacts()
170+
171+ def get_contact_by_name(self,
172+ contact_name,
173+ parent_delegate_type='ContactDelegate'):
174+ """Find a label with text matching contact name.
175+
176+ :param contact_name: The name of the contact, e.g. 'Fulano de Tal'.
177+ :param parent_delegate_type: 'ContactDelegate' or 'FavoriteDelegate'.
178+ :return: The label for a matching contact.
179+ :raises StateNotFoundError: If the contact_name is not found.
180+
181+ """
182+ try:
183+ assert(lambda: len(self.select_many("Label",
184+ text=contact_name)),
185+ Eventually(GreaterThan(0)))
186+ contact_name_labels = self.select_many(
187+ "Label",
188+ text=contact_name)
189+ for contact_name_label in contact_name_labels:
190+ # we could have a contact or a favorite
191+ if get_nearest_parent_matching_type(
192+ contact_name_label,
193+ parent_delegate_type):
194+ return contact_name_label
195+ raise StateNotFoundError('Label')
196+ except StateNotFoundError:
197+ logger.error("Contact {} not found.".format(contact_name))
198+ raise
199+
200+ def get_favorite_by_name(self, contact_name):
201+ """Find a label with text matching contact name under Favorites.
202+
203+ :param contact_name: Name of the contact, e.g. 'Fulano de Tal'.
204+ :return: The label for the metching favorite.
205+ :raises StateNotFoundError: If the contact_name is not found.
206+
207+ """
208+ return self.get_contact_by_name(contact_name).visible
209+
210+ @autopilot_logging.log_action(logger.info)
211+ def click_contact_by_name(self,
212+ contact_name,
213+ parent_delegate_type='ContactDelegate'):
214+ """Click a contact with label matching the given contact name.
215+
216+ :param contact_name: Name of a contact, e.g. 'Fulano de Tal'.
217+ :param parent_delegate_type: 'ContactDelegate' or 'FavoriteDelegate'.
218+ :raises StateNotFoundError: If the contact_name is not found.
219+
220+ """
221+ contact_name_label = self.get_contact_by_name(
222+ contact_name, parent_delegate_type)
223+ self.pointing_device.click_object(contact_name_label)
224+
225+ @autopilot_logging.log_action(logger.info)
226+ def open_contact_view_by_contact_name(self, contact_name):
227+ """Open the contact view page for a contact with the given name.
228+
229+ :param contact_name: The name of the contact, e.g. 'Abe Lincoln'.
230+ :return: The ContactView for the contact.
231+ :raises StateNotFoundError: If the name is not found.
232+
233+ """
234+ self.click_contact_by_name(contact_name)
235+
236+ @autopilot_logging.log_action(logger.info)
237+ def click_favorite_by_name(self,
238+ contact_name):
239+ """Click a favorite with label matching the given contact name.
240+
241+ :param contact_name: Name of a contact, e.g. 'Fulano de Tal'
242+ :raises StateNotFoundError: If the contact_name is not found.
243+
244+ """
245+ contact_name_label = self.get_favorite_by_name(
246+ contact_name)
247+ self.pointing_device.click_object(contact_name_label)
248+
249+ @autopilot_logging.log_action(logger.info)
250+ def open_contact_view_by_favorite_name(self, favorite_name):
251+ """Open the contact view page for a favorite with the given name.
252+
253+ :param favorite_name: The name of the favorite, e.g. 'Abe Lincoln'.
254+ :return: The ContactView for the contact.
255+ :raises StateNotFoundError: If the name is not found.
256+
257+ """
258+ self.click_favorite_by_name(favorite_name)
259+
260+ @autopilot_logging.log_action(logger.info)
261+ def click_phone_number(self, phone_number):
262+ """Click a label matching the given phone number.
263+
264+ :param phone_number: A phone number, e.g. '3321 1232'.
265+ :raises StateNotFoundError: If the phone_number is not found.
266+
267+ """
268+ phone_number_label = self.wait_select_single('Label',
269+ text=phone_number)
270+ self.pointing_device.click_object(phone_number_label)
271+
272+ def contact_is_favorite(self, name):
273+ """Is the given contact name a favorite?
274+
275+ :param contact_name: The name of a contact e.g. John.
276+ :raises StateNotFoundError: If the contact name is not found.
277+ :returns: Boolean.
278+
279+ """
280+ self.open_contact_view_by_contact_name(name)
281
282=== added file 'tests/autopilot/address_book_app/emulators/contact_view.py'
283--- tests/autopilot/address_book_app/emulators/contact_view.py 1970-01-01 00:00:00 +0000
284+++ tests/autopilot/address_book_app/emulators/contact_view.py 2014-03-26 22:14:30 +0000
285@@ -0,0 +1,57 @@
286+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
287+# Copyright 2014 Canonical
288+#
289+# This program is free software: you can redistribute it and/or modify it
290+# under the terms of the GNU General Public License version 3, as published
291+# by the Free Software Foundation.
292+
293+""" ContactView emulator for Addressbook App tests """
294+
295+import logging
296+
297+from autopilot import logging as autopilot_logging
298+from autopilot.introspection.dbus import StateNotFoundError
299+from ubuntuuitoolkit import emulators as uitk
300+
301+logger = logging.getLogger(__name__)
302+
303+
304+class ContactView(uitk.UbuntuUIToolkitEmulatorBase):
305+ """ContactView emulator class"""
306+
307+ def __init__(self, *args):
308+ super(ContactView, self).__init__(*args)
309+
310+ @autopilot_logging.log_action(logger.info)
311+ def click_button(self, objectname):
312+ """Press a button that matches objectname.
313+
314+ :param objectname: The name of the object.
315+ :raises StateNotFoundError: If the matching object is not found.
316+
317+ """
318+ buttons = self.select_single("Button",
319+ objectName=objectname,
320+ visible=True)
321+ self.pointing_device.click_object(button)
322+
323+ @autopilot_logging.log_action(logger.info)
324+ def cancel(self):
325+ """Press the cancel button displayed when pick mode is enabled."""
326+ self.click_button("DialogButtons.rejectButton")
327+
328+ @autopilot_logging.log_action(logger.info)
329+ def delete(self):
330+ """Press the delete button displayed when pick mode is enabled."""
331+ self.click_button("DialogButtons.acceptButton")
332+ self.get_contacts()
333+
334+ def favorite_icon(self):
335+ return self.wait_select_single('Icon', objectName='favoriteIcon')
336+
337+ @autopilot_logging.log_action(logger.info)
338+ def click_favorite_icon(self):
339+ """Tap/click on the favorite icon to make a contact favorite."""
340+ favorite_icon = self.favorite_icon()
341+
342+ self.pointing_device.click_object(favorite_icon)
343
344=== modified file 'tests/autopilot/address_book_app/emulators/main_window.py'
345--- tests/autopilot/address_book_app/emulators/main_window.py 2014-02-28 16:00:02 +0000
346+++ tests/autopilot/address_book_app/emulators/main_window.py 2014-03-26 22:14:30 +0000
347@@ -21,7 +21,7 @@
348
349 def get_contact_list_page(self):
350 return self. wait_select_single("ContactListPage",
351- objectName="contactListPage")
352+ objectName="contactListPage")
353
354 def get_contact_edit_page(self):
355 return self.wait_select_single(ContactEditor,
356@@ -43,7 +43,7 @@
357 """
358 Returns a ContactListView iobject for the current window
359 """
360- return self.wait_select_single( "ContactListView",
361+ return self.wait_select_single("ContactListView",
362 objectName="contactListView")
363
364 def get_button(self, name):
365@@ -53,7 +53,7 @@
366 Arguments:
367 name: Name of the button
368 """
369- return self.wait_select_single( "Button", objectName=name)
370+ return self.wait_select_single("Button", objectName=name)
371
372 def cancel(self):
373 """
374@@ -67,6 +67,30 @@
375 """
376 self.pointing_device.click_object(self.get_button("accept"))
377
378+ def _get_label(self, name):
379+ """
380+ Returns a Label object matching 'name'
381+
382+ Arguments:
383+ name: objectName of the label
384+ """
385+ return self.wait_select_single('Label', objectName=name, visible=True)
386+
387+ def switch_to_favorites(self):
388+ """
389+ switch to the favorite contacts view
390+ """
391+ self.pointing_device.click_object(self._get_label('labelFavorite'))
392+
393+ def switch_to_all_contact(self):
394+ """
395+ Switch to all contacts view
396+ """
397+ self.pointing_device.click_object(self._get_label('labelAll'))
398+
399+ def are_favorites_shown(self):
400+ return self.get_contact_list_view().showFavourites
401+
402 @autopilot_logging.log_action(logger.info)
403 def go_to_add_contact(self):
404 """
405
406=== added file 'tests/autopilot/address_book_app/helpers.py'
407--- tests/autopilot/address_book_app/helpers.py 1970-01-01 00:00:00 +0000
408+++ tests/autopilot/address_book_app/helpers.py 2014-03-26 22:14:30 +0000
409@@ -0,0 +1,74 @@
410+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
411+# Copyright 2014 Canonical
412+#
413+# This program is free software: you can redistribute it and/or modify it
414+# under the terms of the GNU General Public License version 3, as published
415+# by the Free Software Foundation.
416+
417+import subprocess
418+
419+from autopilot.testcase import AutopilotTestCase
420+from autopilot.matchers import Eventually
421+from testtools.matchers import Equals
422+
423+import dbus
424+
425+DUMMY_BACKEND_ADDRESS = 'com.canonical.test.pim'
426+
427+
428+class DummyServiceBackendSetup(AutopilotTestCase):
429+
430+ def _set_contact_service_dummy_backend_environment_variables(self):
431+ self.patch_environment(
432+ 'CANONICAL_PIN_SERVICE_NAME', DUMMY_BACKEND_ADDRESS
433+ )
434+ self.patch_environment(
435+ 'FOLKS_BACKEND_PATH', self._get_dummy_backend_so_location()
436+ )
437+ self.patch_environment('FOLKS_BACKENDS_ALLOWED', 'dummy')
438+ self.patch_environment('FOLKS_PRIMARY_STORE', 'dummy')
439+
440+ def _get_dummy_backend_so_location(self):
441+ output = subprocess.check_output(
442+ ['locate', '/usr/lib', '--basename', 'dummy.so']
443+ ).split()
444+
445+ if len(output) is 1:
446+ return output[0]
447+ elif len(output) > 1:
448+ for path in output:
449+ if 'address-book-service' in path:
450+ return path
451+ else:
452+ raise RuntimeError(
453+ 'Dummy backend .so not found is address-book-service-dummy'
454+ 'installed ?'
455+ )
456+
457+ def _get_address_book_service_binary_location(self):
458+ output = subprocess.check_output(
459+ ['locate', '/usr/lib', '--basename', 'address-book-service']
460+ ).split()
461+
462+ for path in output:
463+ if 'address-book-service/address-book-service' in path:
464+ return path
465+
466+ def _start_service_dummy_backend(self):
467+ self.service = subprocess.Popen(
468+ [self._get_address_book_service_binary_location()]
469+ )
470+ self.addCleanup(self.service.kill)
471+
472+ self.assertThat(
473+ lambda: self._is_dummy_backend_up(), Eventually(Equals(True))
474+ )
475+
476+ def _is_dummy_backend_up(self):
477+ interfaces = dbus.SessionBus().list_names()
478+
479+ return DUMMY_BACKEND_ADDRESS in interfaces
480+
481+ def ensure_dummy_service_backend_running(self):
482+ self._set_contact_service_dummy_backend_environment_variables()
483+ self._start_service_dummy_backend()
484
485=== modified file 'tests/autopilot/address_book_app/tests/__init__.py'
486--- tests/autopilot/address_book_app/tests/__init__.py 2014-01-30 08:35:04 +0000
487+++ tests/autopilot/address_book_app/tests/__init__.py 2014-03-26 22:14:30 +0000
488@@ -18,6 +18,7 @@
489 from testtools.matchers import Equals
490
491 from address_book_app.emulators.main_window import MainWindow
492+
493 from ubuntuuitoolkit import emulators as toolkit_emulators
494
495
496@@ -31,6 +32,7 @@
497 VCARD_PATH_DEV = os.path.abspath("../data/vcard.vcf")
498 ARGS = []
499 PRELOAD_VCARD = False
500+ QTCONTACTS_MANAGER_OVERRIDE_MEMORY = True
501
502 def setUp(self):
503 self.pointing_device = toolkit_emulators.get_pointing_device()
504@@ -45,8 +47,17 @@
505 else:
506 self.app_bin = AddressBookAppTestCase.DEFAULT_DEV_LOCATION
507
508- os.environ['QTCONTACTS_MANAGER_OVERRIDE'] = 'memory'
509+ print "Running from: %s" % (self.app_bin)
510+ # NOTE defeats favoriting: contacts don't show up in "Favorites" header
511+ if AddressBookAppTestCase.QTCONTACTS_MANAGER_OVERRIDE_MEMORY:
512+ os.environ['QTCONTACTS_MANAGER_OVERRIDE'] = 'memory'
513+ else:
514+ try:
515+ del(os.environ['QTCONTACTS_MANAGER_OVERRIDE'])
516+ except KeyError:
517+ pass
518 vcard_data = ""
519+
520 if AddressBookAppTestCase.PRELOAD_VCARD:
521 # Use vcard from source tree and fallback on installed vcard (from
522 # address-book-app-autopilot package)
523@@ -55,16 +66,16 @@
524 else:
525 vcard_data = AddressBookAppTestCase.VCARD_PATH_BIN
526
527- os.environ["ADDRESS_BOOK_TEST_DATA"] = vcard_data
528- if vcard_data != "": print "Using vcard %s" % vcard_data
529+ os.environ['ADDRESS_BOOK_TEST_DATA'] = vcard_data
530+ if vcard_data != '': print 'Using vcard %s' % vcard_data
531 if os.path.exists(self.app_bin):
532- print "Running from: %s" % (self.app_bin)
533+ print 'Running from: %s' % (self.app_bin)
534 self.launch_test_local()
535 elif os.path.exists(self.DEB_LOCALTION):
536- print "Running from: %s" % (self.DEB_LOCALTION)
537+ print 'Running from: %s' % (self.DEB_LOCALTION)
538 self.launch_test_installed()
539 else:
540- print "Running from click package: address-book-app"
541+ print 'Running from click package: address-book-app'
542 self.launch_click_installed()
543
544 AddressBookAppTestCase.ARGS = []
545
546=== modified file 'tests/autopilot/address_book_app/tests/test_add_contact.py'
547--- tests/autopilot/address_book_app/tests/test_add_contact.py 2014-02-28 15:36:09 +0000
548+++ tests/autopilot/address_book_app/tests/test_add_contact.py 2014-03-26 22:14:30 +0000
549@@ -20,6 +20,10 @@
550 class TestAddContact(AddressBookAppTestCase):
551 """ Tests the Add contact """
552
553+ def setUp(self):
554+ AddressBookAppTestCase.QTCONTACTS_MANAGER_OVERRIDE_MEMORY = True
555+ super(TestAddContact, self).setUp()
556+
557 def test_go_to_add_contact(self):
558 """Test to launch the add contact screen using emulator method"""
559 self.assertRaises(
560
561=== modified file 'tests/autopilot/address_book_app/tests/test_contactlist.py'
562--- tests/autopilot/address_book_app/tests/test_contactlist.py 2013-11-21 18:53:19 +0000
563+++ tests/autopilot/address_book_app/tests/test_contactlist.py 2014-03-26 22:14:30 +0000
564@@ -18,6 +18,10 @@
565 class TestContactList(AddressBookAppTestCase):
566 """Tests the contact list features"""
567
568+ def setUp(self):
569+ AddressBookAppTestCase.QTCONTACTS_MANAGER_OVERRIDE_MEMORY = True
570+ super(TestContactList, self).setUp()
571+
572 def test_contact_list(self):
573 contact_list = self.main_window.get_contact_list_page()
574 self.assertThat(contact_list.visible, Eventually(Equals(True)))
575
576=== modified file 'tests/autopilot/address_book_app/tests/test_delete_contact.py'
577--- tests/autopilot/address_book_app/tests/test_delete_contact.py 2014-02-13 16:44:12 +0000
578+++ tests/autopilot/address_book_app/tests/test_delete_contact.py 2014-03-26 22:14:30 +0000
579@@ -40,6 +40,7 @@
580 ]
581
582 def setUp(self):
583+ AddressBookAppTestCase.QTCONTACTS_MANAGER_OVERRIDE_MEMORY = True
584 AddressBookAppTestCase.PRELOAD_VCARD = True
585 super(TestDeleteSelectContact, self).setUp()
586
587
588=== modified file 'tests/autopilot/address_book_app/tests/test_edit_contact.py'
589--- tests/autopilot/address_book_app/tests/test_edit_contact.py 2014-03-18 21:13:04 +0000
590+++ tests/autopilot/address_book_app/tests/test_edit_contact.py 2014-03-26 22:14:30 +0000
591@@ -17,6 +17,10 @@
592 class TestEditContact(AddressBookAppTestCase):
593 """Tests edit a contact"""
594
595+ def setUp(self):
596+ AddressBookAppTestCase.QTCONTACTS_MANAGER_OVERRIDE_MEMORY = True
597+ super(TestEditContact, self).setUp()
598+
599 def test_add_new_phone(self):
600 self.add_contact("Fulano", "de Tal", ["3321 2300"])
601 edit_page = self.edit_contact(0)
602
603=== added file 'tests/autopilot/address_book_app/tests/test_favorites.py'
604--- tests/autopilot/address_book_app/tests/test_favorites.py 1970-01-01 00:00:00 +0000
605+++ tests/autopilot/address_book_app/tests/test_favorites.py 2014-03-26 22:14:30 +0000
606@@ -0,0 +1,96 @@
607+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
608+# Copyright 2014 Canonical
609+#
610+# This program is free software: you can redistribute it and/or modify it
611+# under the terms of the GNU General Public License version 3, as published
612+# by the Free Software Foundation.
613+
614+"""Tests of favoriting contacts for the Addressbook App"""
615+
616+from __future__ import absolute_import
617+
618+import subprocess
619+
620+from autopilot.introspection.dbus import StateNotFoundError
621+from autopilot.matchers import Eventually
622+from testtools.matchers import Equals
623+
624+from address_book_app.helpers import DummyServiceBackendSetup
625+from address_book_app.tests import AddressBookAppTestCase
626+from address_book_app.emulators.contact_list_page import ContactListPage
627+from address_book_app.emulators.contact_view import ContactView
628+
629+
630+class TestFavorite(AddressBookAppTestCase, DummyServiceBackendSetup):
631+ """Test for favoriting contacts"""
632+
633+ def setUp(self):
634+ AddressBookAppTestCase.QTCONTACTS_MANAGER_OVERRIDE_MEMORY = False
635+ AddressBookAppTestCase.PRELOAD_VCARD = True
636+ self.ensure_dummy_service_backend_running()
637+ super(TestFavorite, self).setUp()
638+
639+ def _add_contact_as_favorite(self, name):
640+ contact_list_page = self.main_window.get_contact_list_page()
641+ contact_list_page.open_contact_view_by_contact_name(name)
642+ contact_view = self.main_window.get_contact_view_page()
643+ contact_view.click_favorite_icon()
644+ self.main_window.go_back()
645+ self._ensure_favorites_shown()
646+
647+ return contact_list_page
648+
649+ def _ensure_favorites_shown(self):
650+ if not self.main_window.are_favorites_shown():
651+ self.main_window.switch_to_favorites()
652+ self.main_window.are_favorites_shown().wait_for(True)
653+
654+ def is_contact_favorite(self, name):
655+ contact_list_page = self.main_window.get_contact_list_page()
656+ contact_list_page.open_contact_view_by_contact_name(name)
657+
658+ contact_view = self.main_window.get_contact_view_page()
659+ favorite_icon = contact_view.favorite_icon()
660+
661+ if favorite_icon.name == 'favorite-selected':
662+ return True
663+ else:
664+ return False
665+
666+ def test_add_favorite(self):
667+ """Ensure a contact can be made a favorite."""
668+ self._add_contact_as_favorite('teste test34')
669+
670+ self.assertTrue(self.is_contact_favorite('teste test34'))
671+
672+ def test_save_multiple_favorites(self):
673+ """Ensure multiple contacts can be made favorites."""
674+ self._add_contact_as_favorite('teste test34')
675+ self.assertTrue(self.is_contact_favorite('teste test34'))
676+
677+ self.main_window.go_back()
678+ self.main_window.switch_to_all_contact()
679+
680+ contact_list_page = self._add_contact_as_favorite('teste teste2')
681+ self.assertTrue(self.is_contact_favorite('teste teste2'))
682+
683+ def test_remove_favorite(self):
684+ """Ensure an already favorite contact can be un-favorited."""
685+ contact_list_page = self._add_contact_as_favorite('teste test34')
686+ contact_list_page.open_contact_view_by_contact_name('teste test34')
687+ contact_view = self.main_window.get_contact_view_page()
688+ contact_view.click_favorite_icon()
689+
690+ self.assertFalse(contact_list_page.get_favorite_by_name('teste test34'))
691+
692+ def test_delete_favorite(self):
693+ """Ensure deleting a favorite contact also removes it from favorite
694+ category."""
695+ contact_list_page = self._add_contact_as_favorite('teste test34')
696+ contact_list_page.open_contact_view_by_contact_name('teste test34')
697+ toolbar = self.main_window.open_toolbar()
698+ toolbar.click_button('delete')
699+
700+ self.assertRaises(
701+ StateNotFoundError,
702+ lambda: contact_list_page.get_favorite_by_name('teste test34'))
703
704=== modified file 'tests/autopilot/address_book_app/tests/test_multiple_pick_mode.py'
705--- tests/autopilot/address_book_app/tests/test_multiple_pick_mode.py 2013-12-13 19:31:33 +0000
706+++ tests/autopilot/address_book_app/tests/test_multiple_pick_mode.py 2014-03-26 22:14:30 +0000
707@@ -20,6 +20,7 @@
708
709 def setUp(self):
710 self.ARGS.append("addressbook:///pick?single=false")
711+ AddressBookAppTestCase.QTCONTACTS_MANAGER_OVERRIDE_MEMORY = True
712 AddressBookAppTestCase.PRELOAD_VCARD = True
713 super(TestMultiplePickerMode, self).setUp()
714
715
716=== modified file 'tests/autopilot/address_book_app/tests/test_single_pick_mode.py'
717--- tests/autopilot/address_book_app/tests/test_single_pick_mode.py 2013-12-13 19:31:33 +0000
718+++ tests/autopilot/address_book_app/tests/test_single_pick_mode.py 2014-03-26 22:14:30 +0000
719@@ -21,6 +21,7 @@
720 def setUp(self):
721 AddressBookAppTestCase.ARGS.append("addressbook:///pick?single=true")
722 AddressBookAppTestCase.PRELOAD_VCARD = True
723+ AddressBookAppTestCase.QTCONTACTS_MANAGER_OVERRIDE_MEMORY = True
724 super(TestSinglePickerMode, self).setUp()
725
726 def test_select_single_contact(self):

Subscribers

People subscribed via source and target branches

to all changes: