Merge lp:~elopio/ubuntu-calendar-app/fix1332173-swipe_to_create_new_event into lp:ubuntu-calendar-app

Proposed by Leo Arias
Status: Merged
Approved by: Nicholas Skaggs
Approved revision: 347
Merged at revision: 337
Proposed branch: lp:~elopio/ubuntu-calendar-app/fix1332173-swipe_to_create_new_event
Merge into: lp:ubuntu-calendar-app
Diff against target: 872 lines (+524/-183)
9 files modified
DeleteConfirmationDialog.qml (+2/-0)
EventBubble.qml (+7/-5)
EventDetails.qml (+6/-0)
NewEvent.qml (+1/-0)
tests/autopilot/calendar_app/data.py (+57/-0)
tests/autopilot/calendar_app/emulators.py (+322/-122)
tests/autopilot/calendar_app/tests/test_custom_proxy_objects.py (+30/-0)
tests/autopilot/calendar_app/tests/test_data.py (+30/-0)
tests/autopilot/calendar_app/tests/test_new_event.py (+69/-56)
To merge this branch: bzr merge lp:~elopio/ubuntu-calendar-app/fix1332173-swipe_to_create_new_event
Reviewer Review Type Date Requested Status
Nicholas Skaggs (community) Approve
Ubuntu Phone Apps Jenkins Bot continuous-integration Approve
Review via email: mp+224735@code.launchpad.net

Commit message

Refactored the autopilot test to add a new event. Added helpers and self tests for them.

To post a comment you must log in.
341. By Leo Arias

Removed unused code.

342. By Leo Arias

Added the name to get_events, fixed pep8.

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Needs Fixing (continuous-integration)
343. By Leo Arias

Wait for the events to appear.

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Leo Arias (elopio) wrote :

Three greens in a row, and I've also ran it many times on my machine and on my phone. I'd say this is good to go.

344. By Leo Arias

Reverted the po changes.

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
345. By Leo Arias

Added a comment to the autopilot bug that prevents us to change the date.

346. By Leo Arias

Promoted the duplicates to XXX.

347. By Leo Arias

Removed the unused page.

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Nicholas Skaggs (nskaggs) wrote :

LGTM

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'DeleteConfirmationDialog.qml'
--- DeleteConfirmationDialog.qml 2014-04-13 02:03:43 +0000
+++ DeleteConfirmationDialog.qml 2014-06-27 16:55:37 +0000
@@ -4,6 +4,7 @@
44
5Dialog {5Dialog {
6 id: dialogue6 id: dialogue
7 objectName: "deleteConfirmationDialog"
78
8 property var event;9 property var event;
910
@@ -28,6 +29,7 @@
28 }29 }
2930
30 Button {31 Button {
32 objectName: "deleteEventButton"
31 text: event.parentId ? i18n.tr("Delete this") : i18n.tr("Delete")33 text: event.parentId ? i18n.tr("Delete this") : i18n.tr("Delete")
32 color: UbuntuColors.orange34 color: UbuntuColors.orange
33 onClicked: {35 onClicked: {
3436
=== modified file 'EventBubble.qml'
--- EventBubble.qml 2014-06-21 03:37:43 +0000
+++ EventBubble.qml 2014-06-27 16:55:37 +0000
@@ -133,8 +133,9 @@
133133
134 Label{134 Label{
135 id: timeLabel135 id: timeLabel
136 fontSize:"small";136 objectName: "timeLabel"
137 color:"gray"137 fontSize: "small"
138 color: "gray"
138 width: parent.width - rect.width139 width: parent.width - rect.width
139 }140 }
140 Rectangle{141 Rectangle{
@@ -147,15 +148,16 @@
147 }148 }
148 Label{149 Label{
149 id: titleLabel150 id: titleLabel
150 fontSize:"small";151 objectName: "titleLabel"
151 color:"black"152 fontSize: "small"
153 color: "black"
152 wrapMode: Text.WrapAtWordBoundaryOrAnywhere154 wrapMode: Text.WrapAtWordBoundaryOrAnywhere
153 width: parent.width155 width: parent.width
154 }156 }
155157
156 Label{158 Label{
157 id: descriptionLabel159 id: descriptionLabel
158 fontSize:"small";160 fontSize: "small"
159 color:"gray"161 color:"gray"
160 wrapMode: Text.WrapAtWordBoundaryOrAnywhere162 wrapMode: Text.WrapAtWordBoundaryOrAnywhere
161 width: parent.width163 width: parent.width
162164
=== modified file 'EventDetails.qml'
--- EventDetails.qml 2014-05-27 11:28:27 +0000
+++ EventDetails.qml 2014-06-27 16:55:37 +0000
@@ -9,6 +9,7 @@
99
10Page {10Page {
11 id: root11 id: root
12 objectName: "eventDetails"
1213
13 property var event;14 property var event;
14 property string headerColor :"black"15 property string headerColor :"black"
@@ -165,6 +166,7 @@
165 ToolbarButton {166 ToolbarButton {
166 action:Action {167 action:Action {
167 text: i18n.tr("Delete");168 text: i18n.tr("Delete");
169 objectName: "delete"
168 iconSource: "image://theme/delete,edit-delete-symbolic"170 iconSource: "image://theme/delete,edit-delete-symbolic"
169 onTriggered: {171 onTriggered: {
170 var dialog = PopupUtils.open(Qt.resolvedUrl("DeleteConfirmationDialog.qml"),root,{"event": event});172 var dialog = PopupUtils.open(Qt.resolvedUrl("DeleteConfirmationDialog.qml"),root,{"event": event});
@@ -274,6 +276,7 @@
274 ThinDivider{}276 ThinDivider{}
275 Label{277 Label{
276 id: titleLabel278 id: titleLabel
279 objectName: "titleLabel"
277 fontSize: "large"280 fontSize: "large"
278 width: parent.width281 width: parent.width
279 wrapMode: Text.WordWrap282 wrapMode: Text.WordWrap
@@ -281,6 +284,7 @@
281 }284 }
282 Label{285 Label{
283 id: descLabel286 id: descLabel
287 objectName: "descriptionLabel"
284 wrapMode: Text.WordWrap288 wrapMode: Text.WordWrap
285 fontSize: "small"289 fontSize: "small"
286 width: parent.width290 width: parent.width
@@ -293,6 +297,7 @@
293 }297 }
294 Label{298 Label{
295 id: locationLabel299 id: locationLabel
300 objectName: "locationLabel"
296 fontSize: "medium"301 fontSize: "medium"
297 width: parent.width302 width: parent.width
298 wrapMode: Text.WordWrap303 wrapMode: Text.WordWrap
@@ -322,6 +327,7 @@
322 //Guest Entery Model starts327 //Guest Entery Model starts
323 Column{328 Column{
324 id: contactList329 id: contactList
330 objectName: 'contactList'
325 spacing: units.gu(1)331 spacing: units.gu(1)
326 width: parent.width332 width: parent.width
327 clip: true333 clip: true
328334
=== modified file 'NewEvent.qml'
--- NewEvent.qml 2014-06-19 13:21:24 +0000
+++ NewEvent.qml 2014-06-27 16:55:37 +0000
@@ -11,6 +11,7 @@
1111
12Page {12Page {
13 id: root13 id: root
14 objectName: 'newEventPage'
14 property var date;15 property var date;
1516
16 property var event:null;17 property var event:null;
1718
=== added file 'tests/autopilot/calendar_app/data.py'
--- tests/autopilot/calendar_app/data.py 1970-01-01 00:00:00 +0000
+++ tests/autopilot/calendar_app/data.py 2014-06-27 16:55:37 +0000
@@ -0,0 +1,57 @@
1# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2#
3# Copyright (C) 2014 Canonical Ltd
4#
5# This program is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License version 3 as
7# published by the Free Software Foundation.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17import uuid
18
19
20class DataMixin(object):
21
22 """Mixin with common methods for data objects."""
23
24 def __repr__(self):
25 return '%s(%r)' % (self.__class__, self.__dict__)
26
27 def __eq__(self, other):
28 return (isinstance(other, self.__class__) and
29 self.__dict__ == other.__dict__)
30
31 def __ne__(self, other):
32 return not self.__eq__(other)
33
34
35class Event(DataMixin):
36
37 """Event data object for user acceptance tests."""
38
39 def __init__(self, name, description, location, guests):
40 # TODO add start date and end date, is all day event, recurrence and
41 # reminders. --elopio - 2014-06-26
42 super(Event, self).__init__()
43 self.name = name
44 self.description = description
45 self.location = location
46 self.guests = guests
47
48 @classmethod
49 def make_unique(cls, unique_id=None):
50 """Return a unique event."""
51 if unique_id is None:
52 unique_id = str(uuid.uuid1())
53 name = 'Test event {}'.format(unique_id)
54 description = 'Test description {}.'.format(unique_id)
55 location = 'Test location {}'.format(unique_id)
56 guests = ['Test guest {} 1'.format(unique_id)]
57 return cls(name, description, location, guests)
058
=== modified file 'tests/autopilot/calendar_app/emulators.py'
--- tests/autopilot/calendar_app/emulators.py 2014-06-26 18:10:28 +0000
+++ tests/autopilot/calendar_app/emulators.py 2014-06-27 16:55:37 +0000
@@ -15,20 +15,28 @@
15# along with this program. If not, see <http://www.gnu.org/licenses/>.15# along with this program. If not, see <http://www.gnu.org/licenses/>.
1616
17"""Calendar app autopilot emulators."""17"""Calendar app autopilot emulators."""
18
19import logging
18from time import sleep20from time import sleep
1921
20from autopilot.introspection import dbus22import autopilot.logging
2123from dateutil import tz
2224
25import ubuntuuitoolkit
23from ubuntuuitoolkit import (26from ubuntuuitoolkit import (
24 emulators as toolkit_emulators,27 emulators as toolkit_emulators,
25 pickers28 pickers
26)29)
27from dateutil import tz30
2831from calendar_app import data
2932
30class NewEventEntryField(toolkit_emulators.TextField):33
31 """Autopilot helper for the NewEventEntryField component."""34logger = logging.getLogger(__name__)
35
36
37class CalendarException(ubuntuuitoolkit.ToolkitException):
38
39 """Exception raised when there are problems with the Calendar."""
3240
3341
34# for now we are borrowing the textfield helper for the textarea42# for now we are borrowing the textfield helper for the textarea
@@ -40,9 +48,32 @@
4048
41class MainView(toolkit_emulators.MainView):49class MainView(toolkit_emulators.MainView):
4250
43 """51 """An emulator that makes it easy to interact with the calendar-app."""
44 An emulator class that makes it easy to interact with the calendar-app.52
45 """53 @autopilot.logging.log_action(logger.info)
54 def go_to_day_view(self):
55 """Open the day view.
56
57 :return: The Day View page.
58
59 """
60 day_tab = self.select_single('Tab', objectName='dayTab')
61 if not day_tab.visible:
62 self.switch_to_tab('dayTab')
63 else:
64 logger.debug('The Day View page is already opened.')
65 return day_tab.select_single(DayView, objectName='DayView')
66
67 @autopilot.logging.log_action(logger.info)
68 def go_to_new_event(self):
69 """Open the page to add a new event.
70
71 :return: The New Event page.
72
73 """
74 header = self.get_header()
75 header.click_action_button('neweventbutton')
76 return self.select_single(NewEvent, objectName='newEventPage')
4677
47 def set_picker(self, field, mode, value):78 def set_picker(self, field, mode, value):
48 # open picker79 # open picker
@@ -85,52 +116,6 @@
85 else:116 else:
86 return None117 return None
87118
88 def get_new_event(self):
89 try:
90 return self.wait_select_single("NewEvent")
91 except dbus.StateNotFoundError:
92 return None
93
94 def get_new_event_name_input_box(self):
95 new_event = self.get_new_event()
96 return new_event.wait_select_single(NewEventEntryField,
97 objectName="newEventName")
98
99 def get_event_start_time_field(self):
100 new_event = self.get_new_event()
101 return new_event.wait_select_single(NewEventEntryField,
102 objectName="startTimeInput")
103
104 def get_event_start_date_field(self):
105 new_event = self.get_new_event()
106 return new_event.wait_select_single(NewEventEntryField,
107 objectName="startDateInput")
108
109 def get_event_end_date_field(self):
110 new_event = self.get_new_event()
111 return new_event.wait_select_single(NewEventEntryField,
112 objectName="endDateInput")
113
114 def get_event_end_time_field(self):
115 new_event = self.get_new_event()
116 return new_event.wait_select_single(NewEventEntryField,
117 objectName="endTimeInput")
118
119 def get_event_location_field(self):
120 new_event = self.get_new_event()
121 return new_event.wait_select_single(NewEventEntryField,
122 objectName="eventLocationInput")
123
124 def get_event_people_field(self):
125 new_event = self.get_new_event()
126 return new_event.wait_select_single(NewEventEntryField,
127 objectName="eventPeopleInput")
128
129 def get_event_description_field(self):
130 new_event = self.get_new_event()
131 return new_event.wait_select_single(TextArea,
132 objectName="eventDescriptionInput")
133
134 def safe_swipe_view(self, direction, view, date):119 def safe_swipe_view(self, direction, view, date):
135 """120 """
136 direction: direction to swip121 direction: direction to swip
@@ -176,74 +161,289 @@
176 return component.wait_select_single(161 return component.wait_select_single(
177 "Label", objectName="monthLabel").text162 "Label", objectName="monthLabel").text
178163
179 def get_num_events(self):
180 return len(self.select_many("EventBubble"))
181
182 def get_event(self, title):
183 """ Return an event by title
184 """
185 events = self.select_many("EventBubble")
186 for event in events:
187 try:
188 event_found = event.select_single("Label", text=title)
189 except:
190 continue
191 if event_found:
192 return event
193
194 return 0
195
196 def get_new_event_save_button(self):
197 new_event = self.get_new_event()
198 return new_event.wait_select_single("Button",
199 objectName="accept")
200
201 def get_new_event_cancel_button(self):
202 new_event = self.get_new_event()
203 return new_event.wait_select_single("Button",
204 objectName="cancel")
205
206 def to_local_date(self, date):164 def to_local_date(self, date):
207 utc = date.replace(tzinfo=tz.tzutc())165 utc = date.replace(tzinfo=tz.tzutc())
208 local = utc.astimezone(tz.tzlocal())166 local = utc.astimezone(tz.tzlocal())
209 return local167 return local
210168
211169
212class Page(toolkit_emulators.UbuntuUIToolkitEmulatorBase):170class DayView(toolkit_emulators.UbuntuUIToolkitEmulatorBase):
213 """Autopilot helper for Pages."""171
214172 """Autopilot helper for the Day View page."""
215 def __init__(self, *args):173
216 super(Page, self).__init__(*args)174 def get_events(self, filter_duplicates=False):
217 # XXX we need a better way to keep reference to the main view.175 """Return the events for this day.
218 # --elopio - 2014-01-31176
219 self.main_view = self.get_root_instance().select_single(MainView)177 :return: A list with the events. Each event is a tuple with name, start
220178 time and end time.
221 def drag_page_up(self):179
222 """Drag the given page up."""180 """
223 self._drag_page(direction='up')181 event_bubbles = self._get_selected_day_event_bubbles(filter_duplicates)
224182
225 def drag_page_down(self):183 # sort by y, x
226 """Drag the given page down."""184 event_bubbles = sorted(
227 self._drag_page(direction='down')185 event_bubbles,
228186 key=lambda bubble: (bubble.globalRect.y, bubble.globalRect.x))
229 def _drag_page(self, direction):187
230 """Function to drag the page up/down."""188 events = []
231 self._wait_to_stop_moving()189 for event in event_bubbles:
232190 events.append(event.get_information())
233 x, y, w, h = self.globalRect191
234 start_x = stop_x = x + (w / 2)192 return events
235 start_y = y + (h / 2)193
236194 def _get_current_day_component(self):
237 if direction == "down":195 components = self.select_many('TimeLineBaseComponent')
238 stop_y = start_y + h / 3196 for component in components:
239 self.pointing_device.drag(start_x, start_y, stop_x, stop_y)197 if (self.currentDay.datetime.date() ==
240 else:198 component.startDay.datetime.date()):
241 stop_y = start_y - h / 3199 return component
242 self.pointing_device.drag(start_x, start_y, stop_x, stop_y)200 else:
243201 raise CalendarException(
244 self._wait_to_stop_moving()202 'Could not find the current day component.')
245203
246 def _wait_to_stop_moving(self):204 def _get_selected_day_event_bubbles(self, filter_duplicates):
247 self.select_single(205 selected_day = self._get_current_day_component()
248 'QQuickFlickable',206 return self._get_event_bubbles(selected_day, filter_duplicates)
249 objectName='animationContainer').moving.wait_for(False)207
208 def _get_event_bubbles(self, selected_day, filter_duplicates):
209 event_bubbles = selected_day.select_many(EventBubble)
210 if filter_duplicates:
211 # XXX remove this once bug http://pad.lv/1334833 is fixed.
212 # --elopio - 2014-06-26
213 separator_id = selected_day.select_single(
214 'QQuickRectangle', objectName='separator').id
215 event_bubbles = self._remove_duplicate_events(
216 separator_id, event_bubbles)
217 return event_bubbles
218
219 def _remove_duplicate_events(self, separator_id, event_bubbles):
220 events = []
221 for bubble in event_bubbles:
222 if bubble.id > separator_id:
223 events.append(bubble)
224
225 return events
226
227 @autopilot.logging.log_action(logger.info)
228 def open_event(self, name, filter_duplicates=False):
229 """Open an event.
230
231 :param name: The name of the event to open.
232 :return: The Event Details page.
233
234 """
235 event_bubbles = self._get_selected_day_event_bubbles(filter_duplicates)
236 for bubble in event_bubbles:
237 if bubble.get_name() == name:
238 return bubble.open_event()
239 else:
240 raise CalendarException(
241 'Could not find event with name {}.'.format(name))
242
243 @autopilot.logging.log_action(logger.info)
244 def delete_event(self, name, filter_duplicates=False):
245 """Delete an event.
246
247 :param name: The name of the event to delete.
248 :return: The Day View page.
249
250 """
251 event_details_page = self.open_event(name, filter_duplicates)
252 return event_details_page.delete()
253
254
255class EventBubble(toolkit_emulators.UbuntuUIToolkitEmulatorBase):
256
257 """Autopiot helper for the Event Bubble items."""
258
259 def get_information(self):
260 """Return a tuple with the name, start time and end time."""
261 name = self.get_name()
262 start_time, end_time = self._get_start_and_end_time()
263 return name, start_time, end_time
264
265 def _get_start_and_end_time(self):
266 """Return a tuple with the start time and end time."""
267 time_label = self.select_single('Label', objectName='timeLabel')
268 start_time, end_time = time_label.text.split(' - ')
269 return start_time, end_time
270
271 def get_name(self):
272 """Return the event name."""
273 title_label = self.select_single('Label', objectName='titleLabel')
274 return title_label.text
275
276 @autopilot.logging.log_action(logger.info)
277 def open_event(self):
278 """Open the event.
279
280 :return: The Event Details page.
281
282 """
283 # If there are too many events, the center of the bubble
284 # might be hidden by another event. Click the left side of the
285 # bubble.
286 left = self.globalRect.x + 5
287 center_y = self.globalRect.y + self.globalRect.height // 2
288 self.pointing_device.move(left, center_y)
289 self.pointing_device.click()
290 return self.get_root_instance().select_single(
291 EventDetails, objectName='eventDetails')
292
293
294class NewEvent(toolkit_emulators.UbuntuUIToolkitEmulatorBase):
295
296 """Autopilot helper for the New Event page."""
297
298 @autopilot.logging.log_action(logger.info)
299 def add_event(self, event_information):
300 """Add a new event.
301
302 :param event_information: Values of the event to fill the form.
303 :type event_information: data object with the attributes name,
304 description, location and guests.
305 :return: The Day View page.
306
307 """
308 self._fill_form(event_information)
309 self._save()
310 return self.get_root_instance().select_single(
311 DayView, objectName='DayView')
312
313 @autopilot.logging.log_action(logger.debug)
314 def _fill_form(self, event_information):
315 """Fill the add event form.
316
317 :param event_information: Values of the event to fill the form.
318 :type event_information: data object with the attributes name,
319 description, location and guests.
320
321 """
322 # TODO fill start date and end date, is all day event, recurrence and
323 # reminders. --elopio - 2014-06-26
324 if event_information.name is not None:
325 self._fill_name(event_information.name)
326 if event_information.description is not None:
327 self._fill_description(event_information.description)
328 if event_information.location is not None:
329 self._fill_location(event_information.location)
330 if event_information.guests is not None:
331 self._fill_guests(event_information.guests)
332
333 def _fill_name(self, value):
334 self._ensure_entry_field_visible_and_write('newEventName', value)
335
336 def _ensure_entry_field_visible_and_write(self, object_name, value):
337 name_text_field = self._get_new_event_entry_field(object_name)
338 self._ensure_visible_and_write(name_text_field, value)
339
340 def _get_new_event_entry_field(self, object_name):
341 return self.select_single(NewEventEntryField, objectName=object_name)
342
343 def _ensure_visible_and_write(self, text_field, value):
344 text_field.swipe_into_view()
345 text_field.write(value)
346
347 def _fill_description(self, value):
348 description_text_area = self._get_description_text_area()
349 self._ensure_visible_and_write(description_text_area, value)
350
351 def _get_description_text_area(self):
352 return self.select_single(TextArea, objectName='eventDescriptionInput')
353
354 def _fill_location(self, value):
355 self._ensure_entry_field_visible_and_write('eventLocationInput', value)
356
357 def _fill_guests(self, value):
358 if len(value) > 1:
359 # See bug http://pad.lv/1295941
360 raise CalendarException(
361 'It is not yet possible to add more than one guest.')
362 self._ensure_entry_field_visible_and_write(
363 'eventPeopleInput', value[0])
364
365 def _get_form_values(self):
366 # TODO get start date and end date, is all day event, recurrence and
367 # reminders. --elopio - 2014-06-26
368 name = self._get_new_event_entry_field('newEventName').text
369 description = self._get_description_text_area().text
370 location = self._get_new_event_entry_field('eventLocationInput').text
371 # TODO once bug http://pad.lv/1295941 is fixed, we will have to build
372 # the list of guests. --elopio - 2014-06-26
373 guests = [self._get_new_event_entry_field('eventPeopleInput').text]
374 return data.Event(name, description, location, guests)
375
376 @autopilot.logging.log_action(logger.info)
377 def _save(self):
378 """Save the new event."""
379 save_button = self.select_single('Button', objectName='accept')
380 self.pointing_device.click_object(save_button)
381
382
383class NewEventEntryField(toolkit_emulators.TextField):
384
385 """Autopilot helper for the NewEventEntryField component."""
386
387
388class EventDetails(toolkit_emulators.UbuntuUIToolkitEmulatorBase):
389
390 """Autopilot helper for the Event Details page."""
391
392 @autopilot.logging.log_action(logger.debug)
393 def delete(self):
394 """Click the delete button.
395
396 :return: The Day View page.
397
398 """
399 root = self.get_root_instance()
400 header = root.select_single(MainView).get_header()
401 header.click_action_button('delete')
402
403 delete_confirmation_dialog = root.select_single(
404 DeleteConfirmationDialog, objectName='deleteConfirmationDialog')
405 delete_confirmation_dialog.confirm_deletion()
406
407 return root.select_single(DayView, objectName='DayView')
408
409 def get_event_information(self):
410 """Return the information of the event."""
411 name = self._get_name()
412 description = self._get_description()
413 location = self._get_location()
414 guests = self._get_guests()
415 return data.Event(name, description, location, guests)
416
417 def _get_name(self):
418 return self._get_label_text('titleLabel')
419
420 def _get_label_text(self, object_name):
421 return self.select_single('Label', objectName=object_name).text
422
423 def _get_description(self):
424 return self._get_label_text('descriptionLabel')
425
426 def _get_location(self):
427 return self._get_label_text('locationLabel')
428
429 def _get_guests(self):
430 guests = []
431 contacts_list = self.select_single(
432 'QQuickColumn', objectName='contactList')
433 guest_labels = contacts_list.select_many('Label')
434 for label in guest_labels:
435 guests.append(label.text)
436
437 return guests
438
439
440class DeleteConfirmationDialog(toolkit_emulators.UbuntuUIToolkitEmulatorBase):
441
442 """Autopilot helper for the Delete Confirmation dialog."""
443
444 @autopilot.logging.log_action(logger.debug)
445 def confirm_deletion(self):
446 """Confirm the deletion of the event."""
447 delete_button = self.select_single(
448 'Button', objectName='deleteEventButton')
449 self.pointing_device.click_object(delete_button)
250450
=== added file 'tests/autopilot/calendar_app/tests/test_custom_proxy_objects.py'
--- tests/autopilot/calendar_app/tests/test_custom_proxy_objects.py 1970-01-01 00:00:00 +0000
+++ tests/autopilot/calendar_app/tests/test_custom_proxy_objects.py 2014-06-27 16:55:37 +0000
@@ -0,0 +1,30 @@
1# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2#
3# Copyright (C) 2014 Canonical Ltd
4#
5# This program is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License version 3 as
7# published by the Free Software Foundation.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17from calendar_app import data, tests
18
19
20class NewEventFormTestCase(tests.CalendarTestCase):
21
22 def test_fill_form(self):
23 """Test that the form can be filled with event information."""
24 test_event = data.Event.make_unique(unique_id='test uuid')
25
26 new_event_page = new_event_page = self.main_view.go_to_new_event()
27 new_event_page._fill_form(test_event)
28
29 form_values = new_event_page._get_form_values()
30 self.assertEqual(test_event, form_values)
031
=== added file 'tests/autopilot/calendar_app/tests/test_data.py'
--- tests/autopilot/calendar_app/tests/test_data.py 1970-01-01 00:00:00 +0000
+++ tests/autopilot/calendar_app/tests/test_data.py 2014-06-27 16:55:37 +0000
@@ -0,0 +1,30 @@
1# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2#
3# Copyright (C) 2014 Canonical Ltd
4#
5# This program is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License version 3 as
7# published by the Free Software Foundation.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17import testtools
18
19from calendar_app import data
20
21
22class EventTestCase(testtools.TestCase):
23
24 def test_make_unique_event_must_return_event_with_unique_id(self):
25 event = data.Event.make_unique(unique_id='test uuid')
26
27 self.assertEqual(event.name, 'Test event test uuid')
28 self.assertEqual(event.description, 'Test description test uuid.')
29 self.assertEqual(event.location, 'Test location test uuid')
30 self.assertEqual(event.guests, ['Test guest test uuid 1'])
031
=== renamed file 'tests/autopilot/calendar_app/tests/test_calendar.py' => 'tests/autopilot/calendar_app/tests/test_new_event.py'
--- tests/autopilot/calendar_app/tests/test_calendar.py 2014-06-26 18:10:28 +0000
+++ tests/autopilot/calendar_app/tests/test_new_event.py 2014-06-27 16:55:37 +0000
@@ -17,62 +17,75 @@
17"""Calendar app autopilot tests."""17"""Calendar app autopilot tests."""
1818
19from __future__ import absolute_import19from __future__ import absolute_import
20
21import logging
22
20from autopilot.matchers import Eventually23from autopilot.matchers import Eventually
21from testtools.matchers import Not, Is, NotEquals24from testtools.matchers import HasLength
25
26from calendar_app import data
22from calendar_app.tests import CalendarTestCase27from calendar_app.tests import CalendarTestCase
2328
24import time29
2530logger = logging.getLogger(__name__)
2631
27class TestMainView(CalendarTestCase):32
2833class NewEventTestCase(CalendarTestCase):
29 def test_new_event(self):34
30 """test add new event """35 # TODO add tests for events in the future and in the past, all day event,
31 # go to today36 # event with recurrence and event with reminders.
32 self.main_view.switch_to_tab("dayTab")37 # We currently can't change the date of the new event because of bug
33 header = self.main_view.get_header()38 # http://pad.lv/1328600 on Autopilot.
34 header.click_action_button('todaybutton')39 # --elopio - 2014-06-26
35 num_events = self.main_view.get_num_events()40
3641 def try_delete_event(self, event_name, filter_duplicates):
37 # click on new event button42 try:
38 header = self.main_view.get_header()43 day_view = self.main_view.go_to_day_view()
39 header.click_action_button('neweventbutton')44 day_view.delete_event(event_name, filter_duplicates)
40 self.assertThat(self.main_view.get_new_event,45 except Exception as exception:
41 Eventually(Not(Is(None))))46 logger.warn(str(exception))
4247
43 # due to https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/132696348 def test_add_new_event_with_default_values(self):
44 # the first event triggered is ignored, so we trigger an event49 """Test adding a new event with the default values.
45 # and a small sleep to clear before continuing input50
46 event_name_field = self.main_view.get_new_event_name_input_box()51 The event must be created on the currently selected date,
47 self.pointing_device.click_object(event_name_field)52 with an end time, without recurrence and without reminders.
48 time.sleep(1)53
4954 """
50 # input a new event name55 test_event = data.Event.make_unique()
51 eventTitle = "Test event " + str(int(time.time()))56
52 self.main_view.get_new_event_name_input_box().write(eventTitle)57 day_view = self.main_view.go_to_day_view()
5358 original_events = day_view.get_events()
54 # input description59
55 self.main_view.get_event_description_field(). \60 new_event_page = self.main_view.go_to_new_event()
56 write("My favorite test event")61 # XXX remove this once bug http://pad.lv/1334833 is fixed.
5762 # --elopio - 2014-06-26
58 # input location63 filter_duplicates = len(original_events) > 0
59 self.main_view.get_event_location_field().write("England")64 self.addCleanup(
6065 self.try_delete_event, test_event.name, filter_duplicates)
61 # input guests66 day_view = new_event_page.add_event(test_event)
62 self.main_view.get_event_people_field().write("me, myself, and I")67
6368 def get_new_events():
64 # todo: iterate over all combinations69 return day_view.get_events(filter_duplicates)
65 # and include recurrence and reminders70
6671 self.assertThat(
67 # click save button72 get_new_events, Eventually(HasLength(len(original_events) + 1)))
68 save_button = self.main_view.get_new_event_save_button()73 event_details_page = day_view.open_event(test_event.name)
69 self.pointing_device.click_object(save_button)74 self.assertEqual(
7075 test_event, event_details_page.get_event_information())
71 # verify that the event has been created in timeline76
72 self.main_view.switch_to_tab("dayTab")77 def test_delete_event_must_remove_it_from_day_view(self):
73 header = self.main_view.get_header()78 """Test deleting an event must no longer show it on the day view."""
74 header.click_action_button('todaybutton')79 # TODO remove the skip once the bug is fixed. --elopio - 2014-06-26
75 self.assertThat(self.main_view.get_num_events,80 self.skipTest('This test fails because of bug http://pad.lv/1334883')
76 Eventually(NotEquals(num_events)))81 event = data.Event.make_unique()
7782
78 # todo: verify entered event data83 day_view = self.main_view.go_to_day_view()
84 original_events = day_view.get_events()
85
86 new_event_page = self.main_view.go_to_new_event()
87 day_view = new_event_page.add_event(event)
88 day_view = day_view.delete_event(event.name, len(original_events) > 0)
89
90 events_after_delete = day_view.get_events()
91 self.assertEqual(original_events, events_after_delete)

Subscribers

People subscribed via source and target branches

to status/vote changes: