Merge lp:~zsombi/ubuntu-ui-toolkit/alarm-fetch-fix into lp:ubuntu-ui-toolkit

Proposed by Zsombor Egri
Status: Superseded
Proposed branch: lp:~zsombi/ubuntu-ui-toolkit/alarm-fetch-fix
Merge into: lp:ubuntu-ui-toolkit
Diff against target: 906 lines (+452/-91)
12 files modified
components.api (+2/-0)
modules/Ubuntu/Components/plugin/adapters/alarmsadapter_organizer.cpp (+56/-23)
modules/Ubuntu/Components/plugin/adapters/alarmsadapter_p.h (+2/-0)
modules/Ubuntu/Components/plugin/alarmmanager_p.h (+2/-0)
modules/Ubuntu/Components/plugin/ucalarm.cpp (+33/-27)
modules/Ubuntu/Components/plugin/ucalarm_p.h (+1/-1)
modules/Ubuntu/Test/UbuntuTestCase.qml (+69/-1)
modules/Ubuntu/Test/deployment.pri (+6/-1)
tests/resources/alarm/Alarms.qml (+6/-2)
tests/unit/runtest.sh (+1/-1)
tests/unit/tst_alarms/tst_alarms.cpp (+171/-20)
tests/unit_x11/tst_test/tst_ubuntutestcase.qml (+103/-15)
To merge this branch: bzr merge lp:~zsombi/ubuntu-ui-toolkit/alarm-fetch-fix
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve
Cris Dywan Needs Fixing
Review via email: mp+208749@code.launchpad.net

This proposal has been superseded by a proposal from 2014-04-10.

Commit message

Fix alarm fetching order and interval.

To post a comment you must log in.
Revision history for this message
Zsombor Egri (zsombi) wrote :

*DO NOT REVIEW IT YET*

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: Approve (continuous-integration)
Revision history for this message
Renato Araujo Oliveira Filho (renatofilho) wrote :

blank lines:

202 +
203 +

Revision history for this message
Renato Araujo Oliveira Filho (renatofilho) wrote :

Missing debug:

114 + qDebug() << "UPDATE OCCURRENCE" << alarm.message << alarm.date << occurrence.startDateTime();

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
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: Approve (continuous-integration)
Revision history for this message
Nekhelesh Ramananthan (nik90) wrote :

Okay it was just confirmed to me by Pat McGowan that this MP seems to also fix https://bugs.launchpad.net/ubuntu-clock-app/+bug/1283212. I will do another test to absolutely confirm this after which you can attach that bug report to this MP as well :)

Revision history for this message
Nekhelesh Ramananthan (nik90) wrote :

So on testing this MP with the ubuntu-clock-app, here are the following observations,

1. Bug #1283859 doesn't appear to be fixed. The indicator-datetime does not show the updated recurring alarm values despite it being shown in the clock app.

2. Bug #1285958 seemed already fixed with Renato's patch to EDS which one can find at https://code.launchpad.net/~renatofilho/qtorganizer5-eds/fix-1285958/+merge/209791. On talking to zsombi on IRC, he told me that this patch was only for alarms <7 days. While this MP is also meant to fix it for >7 days. However this is not testable using the clock app. Hence I am unable to confirm the fix.

3. It also appears that this MP seemed to have fixed Bug #1283212. This bug was reported by Pat Mcgowan who was able to reproduce the bug in image #229. However after installing this MP, I was unable to reproduce the bug again.

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: Approve (continuous-integration)
Revision history for this message
Cris Dywan (kalikiana) wrote :

// do we get segfault because this is missing?

That's a strange comment. I'd assume you want to a) use deleteLater because you know that it can be used until the next main loop iteration, and have the comment say that, idealy by what b) or you scratch both the comment and the deleterLater if this isn't the case c) or FIXME: Work-around unexplained use of fetchRequest

// with EDS we need to query the occurrences separately as the fetch reports only the main events

Is there a bug on fixing the EDS backend?

// if we are on Monday, the first alarm occurrence is gonna be on Wednesday!

It's very bad to have different test results based on when it runs. I'd rather you mock the date or tweak the environment to test both.

 QString envManager(qgetenv("ALARM_BACKEND"));

Would be good to have a test case to check that this works. And it might best to unconditionally set it so that you don't have to scratch your head on whether it was picked up or not but simply fails or works.

review: Needs Fixing
Revision history for this message
Zsombor Egri (zsombi) wrote :

> // do we get segfault because this is missing?
>
> That's a strange comment. I'd assume you want to a) use deleteLater because
> you know that it can be used until the next main loop iteration, and have the
> comment say that, idealy by what b) or you scratch both the comment and the
> deleterLater if this isn't the case c) or FIXME: Work-around unexplained use
> of fetchRequest

Right, that comment was left there by mistake :)

>
> // with EDS we need to query the occurrences separately as the fetch reports
> only the main events
>
> Is there a bug on fixing the EDS backend?

There was a bug, the fix had landed way before... More than 1 month ago... The fix was made right after the Toolkit's alarm fetch got broken. However, the same logic works well with the memory manager, so basically there's no difference in logic. We skip the occurrences in the main fetch loop anyway, and only memory manager reports occurrences there (in completeFetchAlarms()). If EDS would report occurrences in the same way, we would be in trouble again, performance wise that's unacceptable.

>
> // if we are on Monday, the first alarm occurrence is gonna be on Wednesday!
>
> It's very bad to have different test results based on when it runs. I'd rather
> you mock the date or tweak the environment to test both.

I'll redo the test as it supposed to test whether the first occurrence is the right one. For instance if today is Monday and the occurrence is set to Sunday and Monday, the first occurrence of the alarm should be on Sunday the same week.

>
> QString envManager(qgetenv("ALARM_BACKEND"));
>
> Would be good to have a test case to check that this works. And it might best
> to unconditionally set it so that you don't have to scratch your head on
> whether it was picked up or not but simply fails or works.

This is tricky, as we only have two managers, eds and memory, and eds might not even be available, so I cannot be sure whether that will work. I can only test with arbitrary garbage unavailability....

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Cris Dywan (kalikiana) wrote :

Thanks for the update.

review: Approve
962. By Zsombor Egri

small fixes, stronger tests

963. By Zsombor Egri

trunk merge

Revision history for this message
Cris Dywan (kalikiana) wrote :

// } else if (rawData.type != UCAlarm::OneTime) {

This confused me a bit why OneTime is relevant there.

How about changing checkDow() to avoid != to make it less confusing.

// alarm.setDate(QDateTime::currentDateTime().addDays(1));

Somehow this looks arbitrary. Given the fact that it worked before and the week has neither 5 nor 1 days what exactly is the goal here?

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

kick

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Zsombor Egri (zsombi) wrote :

> // } else if (rawData.type != UCAlarm::OneTime) {
>
> This confused me a bit why OneTime is relevant there.
>
> How about changing checkDow() to avoid != to make it less confusing.

Actually you are right, that is not in the right place there. I've moved the code under the recurring alarm check.

>
> // alarm.setDate(QDateTime::currentDateTime().addDays(1));
>
> Somehow this looks arbitrary. Given the fact that it worked before and the
> week has neither 5 nor 1 days what exactly is the goal here?

It doesn't matter how many days are added. The test checks whether an already created alarm updates properly. I'll revert to the original one.

965. By Zsombor Egri

comments addressed, recurring alarm specific code moved to its proper place

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Zsombor Egri (zsombi) wrote :

> > // } else if (rawData.type != UCAlarm::OneTime) {
> >
> > This confused me a bit why OneTime is relevant there.
> >
> > How about changing checkDow() to avoid != to make it less confusing.
>
> Actually you are right, that is not in the right place there. I've moved the
> code under the recurring alarm check.

And also refactored a bit. The date adjustment wasn't really belonging to that method, so I wiped the block out as the code under checkRecurringAlarm() already does the adjustments.

Revision history for this message
Zsombor Egri (zsombi) wrote :

> > > // } else if (rawData.type != UCAlarm::OneTime) {
> > >
> > > This confused me a bit why OneTime is relevant there.
> > >
> > > How about changing checkDow() to avoid != to make it less confusing.
> >
> > Actually you are right, that is not in the right place there. I've moved the
> > code under the recurring alarm check.
>
> And also refactored a bit. The date adjustment wasn't really belonging to that
> method, so I wiped the block out as the code under checkRecurringAlarm()
> already does the adjustments.

Sorry, checkRepeatingWeekly() I mean :)

966. By Zsombor Egri

date adjustments moved into checkRepeatingWeekly(); date normalization removed from test case, as that is not the ususl way to give datetime to API.

967. By Zsombor Egri

staging merge

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'components.api'
2--- components.api 2014-04-01 12:57:27 +0000
3+++ components.api 2014-04-10 09:49:53 +0000
4@@ -593,6 +593,8 @@
5 function findChild(obj,objectName)
6 function findInvisibleChild(obj,objectName)
7 function mouseMoveSlowly(item,x,y,dx,dy,steps,stepdelay)
8+ function flick(item, x, y, dx, dy, pressTimeout, steps, button, modifiers, delay)
9+ function mouseLongPress(item, x, y, button, modifiers, delay)
10 function tryCompareFunction(func, expectedResult, timeout)
11 plugins.qmltypes
12 name: "InverseMouseAreaType"
13
14=== modified file 'modules/Ubuntu/Components/plugin/adapters/alarmsadapter_organizer.cpp'
15--- modules/Ubuntu/Components/plugin/adapters/alarmsadapter_organizer.cpp 2014-02-21 20:02:29 +0000
16+++ modules/Ubuntu/Components/plugin/adapters/alarmsadapter_organizer.cpp 2014-04-10 09:49:53 +0000
17@@ -21,6 +21,7 @@
18 #include "alarmmanager_p.h"
19 #include "alarmrequest_p.h"
20 #include "alarmsadapter_p.h"
21+#include <qorganizertodooccurrence.h>
22
23 #include <QtCore/QFile>
24 #include <QtCore/QDir>
25@@ -55,11 +56,15 @@
26 , manager(0)
27 , fetchRequest(0)
28 {
29- QOrganizerManager local;
30- bool usingDefaultManager = local.availableManagers().contains(ALARM_MANAGER);
31- manager = (usingDefaultManager) ? new QOrganizerManager(ALARM_MANAGER) : new QOrganizerManager(ALARM_MANAGER_FALLBACK);
32+ QString envManager(qgetenv("ALARM_BACKEND"));
33+ if (!envManager.isEmpty() && QOrganizerManager::availableManagers().contains(envManager)) {
34+ manager = new QOrganizerManager(envManager);
35+ } else {
36+ manager = QOrganizerManager::availableManagers().contains(ALARM_MANAGER) ?
37+ new QOrganizerManager(ALARM_MANAGER) : new QOrganizerManager(ALARM_MANAGER_FALLBACK);
38+ }
39 manager->setParent(q_ptr);
40- if (!usingDefaultManager) {
41+ if (manager->managerName() != ALARM_MANAGER) {
42 qWarning() << "WARNING: default alarm manager not installed, using" << manager->managerName() << "manager.";
43 qWarning() << "This manager may not provide all the needed features.";
44 }
45@@ -114,6 +119,7 @@
46
47 int type, days;
48 in >> alarm.message >> alarm.date >> alarm.sound >> type >> days >> alarm.enabled;
49+ alarm.originalDate = alarm.date;
50 alarm.type = static_cast<UCAlarm::AlarmType>(type);
51 alarm.days = static_cast<UCAlarm::DaysOfWeek>(days);
52
53@@ -142,7 +148,7 @@
54
55 Q_FOREACH(const AlarmData &alarm, alarmList) {
56 out << alarm.message
57- << alarm.date
58+ << alarm.originalDate
59 << alarm.sound
60 << alarm.type
61 << alarm.days
62@@ -157,7 +163,6 @@
63 event.setCollectionId(collection.id());
64 event.setAllDay(false);
65 event.setStartDateTime(alarm.date);
66- event.setDueDateTime(alarm.date);
67 event.setDisplayLabel(alarm.message);
68
69 if (alarm.enabled) {
70@@ -224,8 +229,9 @@
71
72 alarm.cookie = QVariant::fromValue<QOrganizerItemId>(event.id());
73 alarm.message = event.displayLabel();
74- alarm.date = AlarmData::normalizeDate(event.dueDateTime());
75+ alarm.date = AlarmData::normalizeDate(event.startDateTime());
76 alarm.sound = QUrl(event.description());
77+ alarm.originalDate = alarm.date;
78
79 // check if the alarm is enabled or not
80 QOrganizerItemVisualReminder visual = event.detail(QOrganizerItemDetail::TypeVisualReminder);
81@@ -303,8 +309,8 @@
82 Q_FOREACH(const QOrganizerItem &item, alarms) {
83 // repeating alarms may be fetched as occurences, therefore check their parent event
84 if (item.type() == QOrganizerItemType::TypeTodoOccurrence) {
85- QOrganizerTodoOccurrence occurence = static_cast<QOrganizerTodoOccurrence>(item);
86- QOrganizerItemId eventId = occurence.parentId();
87+ QOrganizerTodoOccurrence occurrence = static_cast<QOrganizerTodoOccurrence>(item);
88+ QOrganizerItemId eventId = occurrence.parentId();
89 if (parentId.contains(eventId)) {
90 continue;
91 }
92@@ -317,6 +323,7 @@
93 }
94 AlarmData alarm;
95 if (alarmDataFromOrganizerEvent(event, alarm) == UCAlarm::NoError) {
96+ adjustAlarmOccurrence(event, alarm);
97 alarmList << alarm;
98 }
99 }
100@@ -324,9 +331,48 @@
101 saveAlarms();
102 Q_EMIT q_ptr->alarmsChanged();
103 completed = true;
104+ fetchRequest->deleteLater();
105 fetchRequest = 0;
106 }
107
108+void AlarmsAdapter::adjustAlarmOccurrence(const QOrganizerTodo &event, AlarmData &alarm)
109+{
110+ if (alarm.type == UCAlarm::OneTime) {
111+ return;
112+ }
113+ // with EDS we need to query the occurrences separately as the fetch reports only the main events
114+ // with fallback manager this does not reduce the performance and does work the same way.
115+ QDateTime currentDate = AlarmData::normalizeDate(QDateTime::currentDateTime());
116+ if (alarm.date > currentDate) {
117+ // no need to adjust date, the event occurs in the future
118+ return;
119+ }
120+ QDateTime startDate;
121+ QDateTime endDate;
122+ if (alarm.type == UCAlarm::Repeating) {
123+ // 8 days is enough from the starting date (or current date depending on the start date)
124+ startDate = (alarm.date > currentDate) ? alarm.date : currentDate;
125+ endDate = startDate.addDays(8);
126+ }
127+
128+ QList<QOrganizerItem> occurrences = manager->itemOccurrences(event, startDate, endDate, 10);
129+ // get the first occurrence and use the date from it
130+ if ((occurrences.length() > 0) && (occurrences[0].type() == QOrganizerItemType::TypeTodoOccurrence)) {
131+ // loop till we get a proper future due date
132+ for (int i = 0; i < occurrences.count(); i++) {
133+ QOrganizerTodoOccurrence occurrence = static_cast<QOrganizerTodoOccurrence>(occurrences[i]);
134+ // check if the date is after the current datetime
135+ // the first occurrence is the one closest to the currentDate, therefore we can safely
136+ // set that startDate to the alarm
137+ alarm.date = occurrence.startDateTime();
138+ if (alarm.date > currentDate) {
139+ // we have the proper date set, leave
140+ break;
141+ }
142+ }
143+ }
144+}
145+
146 /*-----------------------------------------------------------------------------
147 * AlarmRequestAdapter implementation
148 */
149@@ -410,23 +456,10 @@
150 QOrganizerItemFetchRequest *operation = new QOrganizerItemFetchRequest(q_ptr);
151 operation->setManager(owner->manager);
152
153- // FIXME: Since returning all events without a limit of date is not a good solution we need to find
154- // a better solution for that.
155- // The current solution filters only the next 7 days (one week).
156- // This will be enough for now, since the current alarms occur weekly, but for the future
157- // we want to allow create alarms with monthly or yearly recurrence
158- QDate currentDate = QDate::currentDate();
159- QDateTime startDate(currentDate,
160- QTime(0,0,0));
161- QDateTime endDate(currentDate.addDays(7),
162- QTime(23,59,59));
163- operation->setStartDate(startDate);
164- operation->setEndDate(endDate);
165-
166 // set sort order
167 QOrganizerItemSortOrder sortOrder;
168 sortOrder.setDirection(Qt::AscendingOrder);
169- sortOrder.setDetail(QOrganizerItemDetail::TypeTodoTime, QOrganizerTodoTime::FieldDueDateTime);
170+ sortOrder.setDetail(QOrganizerItemDetail::TypeTodoTime, QOrganizerTodoTime::FieldStartDateTime);
171 operation->setSorting(QList<QOrganizerItemSortOrder>() << sortOrder);
172
173 // set filter
174
175=== modified file 'modules/Ubuntu/Components/plugin/adapters/alarmsadapter_p.h'
176--- modules/Ubuntu/Components/plugin/adapters/alarmsadapter_p.h 2013-09-18 10:13:04 +0000
177+++ modules/Ubuntu/Components/plugin/adapters/alarmsadapter_p.h 2014-04-10 09:49:53 +0000
178@@ -24,6 +24,7 @@
179
180 #include <qorganizer.h>
181 #include <qorganizermanager.h>
182+#include <qorganizertodo.h>
183
184 QTORGANIZER_USE_NAMESPACE
185
186@@ -78,6 +79,7 @@
187 QOrganizerCollection collection;
188
189 void completeFetchAlarms(const QList<QOrganizerItem> &alarmList);
190+ void adjustAlarmOccurrence(const QOrganizerTodo &event, AlarmData &alarm);
191
192 void loadAlarms();
193 void saveAlarms();
194
195=== modified file 'modules/Ubuntu/Components/plugin/alarmmanager_p.h'
196--- modules/Ubuntu/Components/plugin/alarmmanager_p.h 2013-09-12 05:27:40 +0000
197+++ modules/Ubuntu/Components/plugin/alarmmanager_p.h 2014-04-10 09:49:53 +0000
198@@ -48,6 +48,7 @@
199 AlarmData(const AlarmData &other)
200 : changes(0)
201 , cookie(other.cookie)
202+ , originalDate(other.originalDate)
203 , date(other.date)
204 , message(other.message)
205 , type(other.type)
206@@ -104,6 +105,7 @@
207 QVariant cookie;
208
209 // data members
210+ QDateTime originalDate;
211 QDateTime date;
212 QString message;
213 QUrl sound;
214
215=== modified file 'modules/Ubuntu/Components/plugin/ucalarm.cpp'
216--- modules/Ubuntu/Components/plugin/ucalarm.cpp 2013-09-18 10:25:18 +0000
217+++ modules/Ubuntu/Components/plugin/ucalarm.cpp 2014-04-10 09:49:53 +0000
218@@ -102,15 +102,21 @@
219
220 int UCAlarmPrivate::nextDayOfWeek(UCAlarm::DaysOfWeek days, int fromDay)
221 {
222- if (fromDay <= 0) {
223+ if (fromDay <= 0 || fromDay >= Qt::Sunday) {
224+ // start from the beginning of the week
225 fromDay = Qt::Monday;
226+ } else {
227+ // start checking from the next day onwards
228+ fromDay++;
229 }
230 for (int d = fromDay; d <= Qt::Sunday; d++) {
231 if ((1 << (d - 1)) & days) {
232 return d;
233 }
234 }
235- return 0;
236+
237+ // none found for the rest of the week, return the fist day set
238+ return firstDayOfWeek(days);
239 }
240
241 // checks whether the given num has more than one bit set
242@@ -147,23 +153,14 @@
243 return UCAlarm::NoError;
244 }
245
246-UCAlarm::Error UCAlarmPrivate::checkDow()
247+// adjust dayOfWeek
248+UCAlarm::Error UCAlarmPrivate::adjustDow()
249 {
250 if (!rawData.days) {
251 return UCAlarm::NoDaysOfWeek;
252 } else if (rawData.days == UCAlarm::AutoDetect) {
253 rawData.days = dayOfWeek(rawData.date);
254 rawData.changes |= AlarmData::Days;
255- } else if (rawData.days != UCAlarm::Daily) {
256- int alarmDay = firstDayOfWeek(rawData.days);
257- int dayOfWeek = rawData.date.date().dayOfWeek();
258- if (alarmDay < dayOfWeek) {
259- rawData.date = rawData.date.addDays(7 - dayOfWeek + alarmDay);
260- rawData.changes |= AlarmData::Date;
261- } else if (alarmDay > dayOfWeek) {
262- rawData.date = rawData.date.addDays(alarmDay - dayOfWeek);
263- rawData.changes |= AlarmData::Date;
264- }
265 }
266 return UCAlarm::NoError;
267 }
268@@ -175,8 +172,7 @@
269 return UCAlarm::OneTimeOnMoreDays;
270 }
271
272- // adjust start date and/or dayOfWeek according to their values
273- UCAlarm::Error result = checkDow();
274+ UCAlarm::Error result = adjustDow();
275 if (result != UCAlarm::NoError) {
276 return result;
277 }
278@@ -193,23 +189,25 @@
279 // start date is adjusted depending on the days value;
280 // start date can be set to be the current time, as scheduling will move
281 // it to the first occurence.
282- UCAlarm::Error result = checkDow();
283+ UCAlarm::Error result = adjustDow();
284 if (result != UCAlarm::NoError) {
285 return result;
286 }
287
288- // move start time to the first occurence if needed
289+ // move start time of the first occurence if needed
290 int dayOfWeek = rawData.date.date().dayOfWeek();
291 if (!isDaySet(dayOfWeek, rawData.days) || (rawData.date <= QDateTime::currentDateTime())) {
292 // check the next occurence of the alarm
293- int nextOccurence = nextDayOfWeek(rawData.days, dayOfWeek);
294- if (nextOccurence <= 0) {
295- // the starting date should be moved to the next week
296- nextOccurence = firstDayOfWeek(rawData.days);
297- rawData.date.addDays(7 - dayOfWeek + nextOccurence);
298+ int nextOccurrence = nextDayOfWeek(rawData.days, dayOfWeek);
299+ if (nextOccurrence == dayOfWeek) {
300+ // move the date to the same day next week
301+ rawData.date = rawData.date.addDays(7);
302+ } else if (nextOccurrence < dayOfWeek) {
303+ // the starting date should be moved to the next week's occurrence
304+ rawData.date = rawData.date.addDays(7 - dayOfWeek + nextOccurrence);
305 } else {
306 // the starting date is still this week
307- rawData.date.addDays(nextOccurence - dayOfWeek);
308+ rawData.date = rawData.date.addDays(nextOccurrence - dayOfWeek);
309 }
310 rawData.changes |= AlarmData::Date;
311 }
312@@ -304,7 +302,7 @@
313 : QObject(parent)
314 , d_ptr(new UCAlarmPrivate(this))
315 {
316- d_ptr->rawData.date = dt;
317+ d_ptr->rawData.date = AlarmData::normalizeDate(dt);
318 if (!message.isEmpty()) {
319 d_ptr->rawData.message = message;
320 }
321@@ -315,7 +313,7 @@
322 : QObject(parent)
323 , d_ptr(new UCAlarmPrivate(this))
324 {
325- d_ptr->rawData.date = dt;
326+ d_ptr->rawData.date = AlarmData::normalizeDate(dt);
327 d_ptr->rawData.type = Repeating;
328 d_ptr->rawData.days = days;
329 if (!message.isEmpty()) {
330@@ -366,12 +364,16 @@
331 void UCAlarm::setDate(const QDateTime &date)
332 {
333 Q_D(UCAlarm);
334- if (d->rawData.date == date) {
335+ if (d->rawData.date == AlarmData::normalizeDate(date)) {
336 return;
337 }
338- d->rawData.date = date;
339+ d->rawData.date = AlarmData::normalizeDate(date);
340 d->rawData.changes |= AlarmData::Date;
341 Q_EMIT dateChanged();
342+ if (d->rawData.type == UCAlarm::OneTime) {
343+ // adjust dayOfWeek as well
344+ setDaysOfWeek(UCAlarm::AutoDetect);
345+ }
346 }
347
348 /*!
349@@ -520,6 +522,8 @@
350 Q_EMIT soundChanged();
351 }
352
353+
354+
355 /*!
356 * \qmlproperty Error Alarm::error
357 * The property holds the error code occurred during the last performed operation.
358@@ -670,6 +674,8 @@
359 if (result != UCAlarm::NoError) {
360 d->_q_syncStatus(Saving, Fail, result);
361 } else {
362+ // the alarm has been modified, therefore update the original date as well
363+ d->rawData.originalDate = d->rawData.date;
364 if (d->createRequest()) {
365 d->request->save(d->rawData);
366 }
367
368=== modified file 'modules/Ubuntu/Components/plugin/ucalarm_p.h'
369--- modules/Ubuntu/Components/plugin/ucalarm_p.h 2013-09-18 10:25:18 +0000
370+++ modules/Ubuntu/Components/plugin/ucalarm_p.h 2014-04-10 09:49:53 +0000
371@@ -50,7 +50,7 @@
372 static int nextDayOfWeek(UCAlarm::DaysOfWeek days, int fromDay);
373 static bool multipleDaysSet(UCAlarm::DaysOfWeek days);
374 UCAlarm::Error checkAlarm();
375- UCAlarm::Error checkDow();
376+ UCAlarm::Error adjustDow();
377 UCAlarm::Error checkOneTime();
378 UCAlarm::Error checkRepeatingWeekly();
379
380
381=== modified file 'modules/Ubuntu/Test/UbuntuTestCase.qml'
382--- modules/Ubuntu/Test/UbuntuTestCase.qml 2014-02-25 12:36:27 +0000
383+++ modules/Ubuntu/Test/UbuntuTestCase.qml 2014-04-10 09:49:53 +0000
384@@ -87,7 +87,75 @@
385 }
386 }
387
388- /*!
389+ /*!
390+ \qmlmethod UbuntuTestCase::flick(item, x, y, dx, dy, pressTimeout = -1, steps = -1, button = Qt.LeftButton, modifiers = Qt.NoModifiers, delay = -1)
391+
392+ The function produces a flick event when executed on Flickables. When used
393+ on other components it provides the same functionality as \l mouseDrag()
394+ function. The optional \a pressTimeout parameter can be used to introduce
395+ a small delay between the mouse press and the first mouse move. Setting a
396+ negative or zero value will disable the timeout.
397+
398+ The default flick velocity is built up using 5 move points. This can be altered
399+ by setting a positive value to \a steps parameter. The bigger the number the
400+ longer the flick will be. When a negative or zero value is given, the default
401+ of 5 move points will be used.
402+
403+ \note The function can be used to select a text in a TextField or TextArea by
404+ specifying at least 400 millisecods to \a pressTimeout.
405+ */
406+ function flick(item, x, y, dx, dy, pressTimeout, steps, button, modifiers, delay) {
407+ if (item === undefined || item.x === undefined || item.y === undefined)
408+ return
409+ if (button === undefined)
410+ button = Qt.LeftButton
411+ if (modifiers === undefined)
412+ modifiers = Qt.NoModifier
413+ if (steps === undefined || steps <= 0)
414+ steps = 4;
415+ // make sure we have at least two move steps so the flick will be sensed
416+ steps += 1;
417+ if (delay === undefined)
418+ delay = -1;
419+
420+ var ddx = dx / steps;
421+ var ddy = dy / steps;
422+
423+ mousePress(item, x, y, button, modifiers, delay);
424+ if (pressTimeout !== undefined && pressTimeout > 0) {
425+ wait(pressTimeout);
426+ }
427+ for (var i = 1; i <= steps; i++) {
428+ // mouse moves are all processed immediately, without delay in between events
429+ mouseMove(item, x + i * ddx, y + i * ddy, -1, button);
430+ }
431+ mouseRelease(item, x + dx, y + dy, button, modifiers, delay);
432+ // empty event buffer
433+ wait(200);
434+ }
435+
436+ /*!
437+ \qmlmethod UbuntuTestCase::mouseLongPress(item, x, y, button = Qt.LeftButton, modifiers = Qt.NoModifiers, delay = -1)
438+
439+ Simulates a long press on a mouse \a button with an optional \a modifier
440+ on an \a item. The position is defined by \a x and \a y. If \a delay is
441+ specified, the test will wait the specified amount of milliseconds before
442+ the press.
443+
444+ The position given by \a x and \a y is transformed from the co-ordinate
445+ system of \a item into window co-ordinates and then delivered.
446+ If \a item is obscured by another item, or a child of \a item occupies
447+ that position, then the event will be delivered to the other item instead.
448+
449+ \sa mouseRelease(), mouseClick(), mouseDoubleClick(), mouseMove(), mouseDrag(), mouseWheel()
450+ */
451+ function mouseLongPress(item, x, y, button, modifiers, delay) {
452+ mousePress(item, x, y, button, modifiers, delay);
453+ // the delay is taken from QQuickMouseArea
454+ wait(800);
455+ }
456+
457+ /*!
458 Keeps executing a given parameter-less function until it returns the given
459 expected result or the timemout is reached (in which case a test failure
460 is generated)
461
462=== modified file 'modules/Ubuntu/Test/deployment.pri'
463--- modules/Ubuntu/Test/deployment.pri 2014-01-17 12:30:05 +0000
464+++ modules/Ubuntu/Test/deployment.pri 2014-04-10 09:49:53 +0000
465@@ -7,9 +7,14 @@
466 # make found deployables visible in Qt Creator
467 OTHER_FILES += $$QMLDIR_FILE
468
469+QML_FILES = $$system(ls *.qml)
470+JS_FILES = $$system(ls *.js)
471+
472 # define deployment for found deployables
473 qmldir_file.path = $$installPath
474 qmldir_file.files = $$QMLDIR_FILE
475+qml_files.path = $$installPath
476+qml_files.files = $$QML_FILES
477 js_files.path = $$installPath
478 js_files.files = $$JS_FILES
479
480@@ -20,4 +25,4 @@
481 # https://bugreports.qt-project.org/browse/QTBUG-36243
482 plugins_qmltypes.extra = $$[QT_INSTALL_BINS]/qmlplugindump -notrelocatable Ubuntu.Test 0.1 ../../ 2>/dev/null > $(INSTALL_ROOT)/$$installPath/plugins.qmltypes
483
484-INSTALLS += qmldir_file plugins_qmltypes
485+INSTALLS += qmldir_file plugins_qmltypes qml_files js_files
486
487=== modified file 'tests/resources/alarm/Alarms.qml'
488--- tests/resources/alarm/Alarms.qml 2013-09-18 10:13:04 +0000
489+++ tests/resources/alarm/Alarms.qml 2014-04-10 09:49:53 +0000
490@@ -21,7 +21,7 @@
491
492 MainView {
493 id: mainView
494- width: units.gu(40)
495+ width: units.gu(80)
496 height: units.gu(71)
497 objectName: "mainView"
498
499@@ -162,7 +162,11 @@
500 clip: true
501 model: alarmModel
502 delegate: Standard {
503- text: message
504+ text: message + recurring(model) + "\n" + model.date
505+ function recurring(alarmData) {
506+ return (alarmData.type === Alarm.Repeating) ? "[Repeating]" : "[Onetime]";
507+ }
508+
509 removable: true
510 control: Switch {
511 checked: model.enabled
512
513=== modified file 'tests/unit/runtest.sh'
514--- tests/unit/runtest.sh 2014-03-31 18:26:46 +0000
515+++ tests/unit/runtest.sh 2014-04-10 09:49:53 +0000
516@@ -33,7 +33,7 @@
517 if [ $_TARGET != $_TESTFILE ]; then
518 _CMD="$_CMD -input $_TESTFILE"
519 fi
520- _CMD="$_CMD -maxwarnings 4"
521+ _CMD="$_CMD -maxwarnings 40"
522 }
523
524 function execute_test_cmd {
525
526=== modified file 'tests/unit/tst_alarms/tst_alarms.cpp'
527--- tests/unit/tst_alarms/tst_alarms.cpp 2014-02-21 18:23:41 +0000
528+++ tests/unit/tst_alarms/tst_alarms.cpp 2014-04-10 09:49:53 +0000
529@@ -25,6 +25,7 @@
530 #include "adapters/alarmsadapter_p.h"
531 #undef protected
532
533+#include "uctestcase.h"
534 #include <QtCore/QString>
535 #include <QtCore/QTextCodec>
536 #include <QtCore/QDebug>
537@@ -64,11 +65,18 @@
538 syncFetch();
539 }
540
541- bool containsAlarm(UCAlarm *alarm)
542+ bool containsAlarm(UCAlarm *alarm, bool trace = false)
543 {
544 UCAlarmPrivate *pAlarm = UCAlarmPrivate::get(alarm);
545 QList<AlarmData> alarms = AlarmManager::instance().alarms();
546 Q_FOREACH(AlarmData i, alarms) {
547+ if (trace && (alarm->message() == i.message)) {
548+ qDebug() << "----------------------";
549+ qDebug() << "Alarm data:" << alarm->message();
550+ qDebug() << alarm->date() << i.date;
551+ qDebug() << alarm->type() << i.type;
552+ qDebug() << alarm->daysOfWeek() << i.days;
553+ }
554 if (i == pAlarm->rawData) {
555 return true;
556 }
557@@ -127,7 +135,7 @@
558
559 void test_repeating_autoDetect()
560 {
561- UCAlarm alarm(QDateTime::currentDateTime(), UCAlarm::AutoDetect, "test_repeating_autoDetect");
562+ UCAlarm alarm(QDateTime::currentDateTime().addSecs(20), UCAlarm::AutoDetect, "test_repeating_autoDetect");
563
564 alarm.save();
565 waitForRequest(&alarm);
566@@ -137,28 +145,92 @@
567
568 void test_repeating_daily()
569 {
570- UCAlarm alarm(QDateTime::currentDateTime(), UCAlarm::Daily, "test_repeating_daily");
571-
572- alarm.save();
573- waitForRequest(&alarm);
574- QCOMPARE(alarm.error(), (int)UCAlarm::NoError);
575- QVERIFY(containsAlarm(&alarm));
576- }
577-
578- void test_repeating_givenDay()
579- {
580- UCAlarm alarm(QDateTime::currentDateTime(), UCAlarm::Wednesday, "test_repeating_givenDay");
581-
582- alarm.save();
583- waitForRequest(&alarm);
584- QCOMPARE(alarm.error(), (int)UCAlarm::NoError);
585- QVERIFY(containsAlarm(&alarm));
586+ UCAlarm alarm(QDateTime::currentDateTime().addSecs(10), UCAlarm::Daily, "test_repeating_daily");
587+
588+ alarm.save();
589+ waitForRequest(&alarm);
590+ QCOMPARE(alarm.error(), (int)UCAlarm::NoError);
591+ QVERIFY(containsAlarm(&alarm));
592+ }
593+
594+ void test_repeating_givenDay_exact_data()
595+ {
596+ QTest::addColumn<QString>("message");
597+ QTest::addColumn<int>("day");
598+
599+ QTest::newRow("Monday") << "Monday" << (int)UCAlarm::Monday;
600+ QTest::newRow("Tuesday") << "Tuesday" << (int)UCAlarm::Tuesday;
601+ QTest::newRow("Wednesday") << "Wednesday" << (int)UCAlarm::Wednesday;
602+ QTest::newRow("Thursday") << "Thursday" << (int)UCAlarm::Thursday;
603+ QTest::newRow("Friday") << "Friday" << (int)UCAlarm::Friday;
604+ QTest::newRow("Saturday") << "Saturday" << (int)UCAlarm::Saturday;
605+ QTest::newRow("Sunday") << "Sunday" << (int)UCAlarm::Sunday;
606+ }
607+
608+ void test_repeating_givenDay_exact()
609+ {
610+ QFETCH(QString, message);
611+ QFETCH(int, day);
612+ UCAlarm alarm(QDateTime::currentDateTime(), (UCAlarm::DaysOfWeek)day, "test_repeating_givenDay_exact_" + message);
613+
614+ alarm.save();
615+ waitForRequest(&alarm);
616+ QCOMPARE(alarm.error(), (int)UCAlarm::NoError);
617+ QVERIFY(containsAlarm(&alarm));
618+ }
619+
620+ void test_repeating_moreDays_data()
621+ {
622+ QTest::addColumn<QString>("message");
623+ QTest::addColumn<int>("days");
624+
625+ QTest::newRow("First on Monday") << "Monday" << (int)(UCAlarm::Monday | UCAlarm::Sunday);
626+ QTest::newRow("First on Tuesday") << "Tuesday" << (int)(UCAlarm::Tuesday | UCAlarm::Monday);
627+ QTest::newRow("First on Wednesday") << "Wednesday" << (int)(UCAlarm::Wednesday | UCAlarm::Tuesday);
628+ QTest::newRow("First on Thursday") << "Thursday" << (int)(UCAlarm::Thursday | UCAlarm::Wednesday);
629+ QTest::newRow("First on Friday") << "Friday" << (int)(UCAlarm::Friday | UCAlarm::Thursday);
630+ QTest::newRow("First on Saturday") << "Saturday" << (int)(UCAlarm::Saturday | UCAlarm::Friday);
631+ QTest::newRow("First on Sunday") << "Sunday" << (int)(UCAlarm::Sunday | UCAlarm::Saturday);
632 }
633
634 void test_repeating_moreDays()
635 {
636- UCAlarm alarm(QDateTime::currentDateTime(), UCAlarm::Monday | UCAlarm::Wednesday, "test_repeating_moreDays");
637-
638+ QFETCH(QString, message);
639+ QFETCH(int, days);
640+
641+ QDateTime currentDate(QDateTime::currentDateTime());
642+
643+ UCAlarm alarm(currentDate, (UCAlarm::DaysOfWeek)days, "test_repeating_moreDays" + message);
644+ // the distance is always 6 days between the occurrences
645+ UCAlarm firstOccurrence(currentDate, alarm.daysOfWeek(), alarm.message());
646+ // make sure we have the same setup as the original one; checkAlarm() adjusts all alarm data
647+ UCAlarmPrivate::get(&firstOccurrence)->checkAlarm();
648+
649+ alarm.save();
650+ waitForRequest(&alarm);
651+ QCOMPARE(alarm.error(), (int)UCAlarm::NoError);
652+ QVERIFY(containsAlarm(&alarm));
653+ QVERIFY(containsAlarm(&firstOccurrence));
654+ }
655+
656+ void test_repeating_weekly_data() {
657+ QTest::addColumn<QString>("message");
658+ QTest::addColumn<int>("dow");
659+
660+ QTest::newRow("Monday") << "Monday" << (int)UCAlarm::Monday;
661+ QTest::newRow("Tuesday") << "Tuesday" << (int)UCAlarm::Tuesday;
662+ QTest::newRow("Wednesday") << "Wednesday" << (int)UCAlarm::Wednesday;
663+ QTest::newRow("Thursday") << "Thursday" << (int)UCAlarm::Thursday;
664+ QTest::newRow("Friday") << "Friday" << (int)UCAlarm::Friday;
665+ QTest::newRow("Saturday") << "Saturday" << (int)UCAlarm::Saturday;
666+ QTest::newRow("Sunday") << "Sunday" << (int)UCAlarm::Sunday;
667+ }
668+ void test_repeating_weekly()
669+ {
670+ QFETCH(QString, message);
671+ QFETCH(int, dow);
672+
673+ UCAlarm alarm(QDateTime::currentDateTime().addSecs(3600), (UCAlarm::DaysOfWeek)dow, "test_repeating_weekly_" + message);
674 alarm.save();
675 waitForRequest(&alarm);
676 QCOMPARE(alarm.error(), (int)UCAlarm::NoError);
677@@ -273,6 +345,85 @@
678 QVERIFY(!containsAlarm(&copy));
679 }
680
681+ void test_updateAlarm_Repeating()
682+ {
683+ UCAlarm alarm(QDateTime::currentDateTime().addMSecs(5000), UCAlarm::AutoDetect, "test_updateAlarm_Repeating");
684+
685+ alarm.save();
686+ waitForRequest(&alarm);
687+ QCOMPARE(alarm.error(), (int)UCAlarm::NoError);
688+ QVERIFY(containsAlarm(&alarm));
689+
690+ alarm.setDate(alarm.date().addDays(1));
691+ alarm.save();
692+ waitForRequest(&alarm);
693+ QCOMPARE(alarm.error(), (int)UCAlarm::NoError);
694+ QVERIFY(containsAlarm(&alarm));
695+
696+ alarm.setDaysOfWeek(UCAlarm::Daily);
697+ alarm.save();
698+ waitForRequest(&alarm);
699+ QCOMPARE(alarm.error(), (int)UCAlarm::NoError);
700+ QVERIFY(containsAlarm(&alarm));
701+ }
702+
703+ void test_fetchAlarmPlus7Days()
704+ {
705+ QDateTime dt = QDateTime::currentDateTime().addDays(10);
706+ UCAlarm alarm(dt, "test_fetchAlarmPlus7Days");
707+
708+ alarm.save();
709+ waitForRequest(&alarm);
710+ QCOMPARE(alarm.error(), (int)UCAlarm::NoError);
711+ QVERIFY(containsAlarm(&alarm));
712+
713+ UCAlarm nextMonth(dt.addMonths(1), "test_fetchAlarmPlus1Month");
714+ nextMonth.save();
715+ waitForRequest(&nextMonth);
716+ QCOMPARE(nextMonth.error(), (int)UCAlarm::NoError);
717+ QVERIFY(containsAlarm(&nextMonth));
718+
719+ UCAlarm nextYear(dt.addYears(1), "test_fetchAlarmPlus1Year");
720+ nextYear.save();
721+ waitForRequest(&nextYear);
722+ QCOMPARE(nextYear.error(), (int)UCAlarm::NoError);
723+ QVERIFY(containsAlarm(&nextYear));
724+ }
725+
726+ void test_correctAlarmOrderDaily()
727+ {
728+ QDate cd = QDate::currentDate();
729+ QTime ct = QTime::currentTime();
730+ QDateTime dt(cd, QTime(ct.hour(), ct.minute(), ct.second() + 2));
731+ QDateTime nextDt(cd.addDays(1), QTime(ct.hour(), ct.minute(), ct.second() + 2));
732+ UCAlarm alarm(dt, UCAlarm::Daily, "test_correctAlarmOrderDaily");
733+ UCAlarm nextAlarm(nextDt, UCAlarm::Daily, "test_correctAlarmOrderDaily");
734+
735+ alarm.save();
736+ waitForRequest(&alarm);
737+ QTest::qWait(2000);
738+ syncFetch();
739+ QCOMPARE(alarm.error(), (int)UCAlarm::NoError);
740+ QVERIFY(containsAlarm(&nextAlarm));
741+ }
742+
743+ void test_correctAlarmOrderWeekly()
744+ {
745+ QDate cd = QDate::currentDate();
746+ QTime ct = QTime::currentTime();
747+ QDateTime dt(cd, QTime(ct.hour(), ct.minute(), ct.second() + 1));
748+ QDateTime nextDt(cd.addDays(7), QTime(ct.hour(), ct.minute(), ct.second() + 1));
749+ UCAlarm alarm(dt, UCAlarm::AutoDetect, "test_correctAlarmOrderWeekly");
750+ UCAlarm nextAlarm(nextDt, UCAlarm::AutoDetect, "test_correctAlarmOrderWeekly");
751+
752+ alarm.save();
753+ waitForRequest(&alarm);
754+ QTest::qWait(2000);
755+ syncFetch();
756+ QCOMPARE(alarm.error(), (int)UCAlarm::NoError);
757+ QVERIFY(containsAlarm(&nextAlarm));
758+ }
759+
760 };
761
762 QTEST_MAIN(tst_UCAlarms)
763
764=== modified file 'tests/unit_x11/tst_test/tst_ubuntutestcase.qml'
765--- tests/unit_x11/tst_test/tst_ubuntutestcase.qml 2014-02-13 10:27:14 +0000
766+++ tests/unit_x11/tst_test/tst_ubuntutestcase.qml 2014-04-10 09:49:53 +0000
767@@ -23,30 +23,57 @@
768 width: 800
769 height: 600
770
771- MouseArea {
772- id: mouseArea
773- objectName: "myMouseArea"
774- anchors.fill: parent
775- hoverEnabled: true
776- property int testX : 0
777- property int testY : 0
778- property int steps : 0
779+ Column {
780+ anchors.fill: parent
781+ MouseArea {
782+ id: mouseArea
783+ objectName: "myMouseArea"
784+ width: parent.width
785+ height: 300
786+ hoverEnabled: true
787+ acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton
788+ property int testX : 0
789+ property int testY : 0
790+ property int steps : 0
791
792- onPositionChanged: {
793- testX = mouseX;
794- testY = mouseY;
795- steps++;
796- }
797+ onPositionChanged: {
798+ testX = mouseX;
799+ testY = mouseY;
800+ steps++;
801+ }
802+ }
803+ Flickable {
804+ id: flicker
805+ width: parent.width
806+ height: 400
807+ contentWidth: rect.width
808+ contentHeight: rect.height
809+ clip: true
810+ Rectangle {
811+ id: rect
812+ color: "blue"
813+ width: 1000
814+ height: 1000
815+ }
816+ }
817 }
818
819 UbuntuTestCase {
820 name: "TestTheUbuntuTestCase"
821 when: windowShown
822
823+ function init() {
824+ mouseArea.steps = 0;
825+ }
826+ function cleanup() {
827+ movementSpy.clear();
828+ longPressSpy.clear();
829+ }
830+
831 function test_mouseMoveSlowly() {
832- mouseMoveSlowly(root,0,0,800,600,10,100);
833+ mouseMoveSlowly(root,0,0,800,300,10,100);
834 compare(mouseArea.testX,800);
835- compare(mouseArea.testY,600);
836+ compare(mouseArea.testY,300);
837 compare(mouseArea.steps,10);
838 }
839
840@@ -58,5 +85,66 @@
841 child = findChild(root,"NoSuchChildHere");
842 compare(child===null,true,"When there is no child, function should return null");
843 }
844+
845+ SignalSpy {
846+ id: longPressSpy
847+ target: mouseArea
848+ signalName: "onPressAndHold"
849+ }
850+
851+ function test_longPress_left() {
852+ longPressSpy.clear();
853+ mouseLongPress(mouseArea, mouseArea.width / 2, mouseArea.height / 2);
854+ longPressSpy.wait();
855+ // cleanup
856+ mouseRelease(mouseArea, mouseArea.width / 2, mouseArea.height / 2);
857+ }
858+
859+ function test_longPress_right() {
860+ longPressSpy.clear();
861+ mouseLongPress(mouseArea, mouseArea.width / 2, mouseArea.height / 2, Qt.RightButton);
862+ longPressSpy.wait();
863+ // cleanup
864+ mouseRelease(mouseArea, mouseArea.width / 2, mouseArea.height / 2, Qt.RightButton);
865+ }
866+
867+ function test_longPress_middle() {
868+ longPressSpy.clear();
869+ mouseLongPress(mouseArea, mouseArea.width / 2, mouseArea.height / 2, Qt.MiddleButton);
870+ longPressSpy.wait();
871+ // cleanup
872+ mouseRelease(mouseArea, mouseArea.width / 2, mouseArea.height / 2, Qt.MiddleButton);
873+ }
874+
875+ SignalSpy {
876+ id: movementSpy
877+ target: flicker
878+ signalName: "onMovementEnded"
879+ }
880+
881+ function test_flick_default() {
882+ flick(flicker, 0, 0, flicker.width, flicker.height);
883+ movementSpy.wait();
884+ }
885+ function test_flick_long() {
886+ flick(flicker, 0, 0, flicker.width, flicker.height, -1, 10);
887+ movementSpy.wait();
888+ }
889+ function test_flick_short() {
890+ flick(flicker, 0, 0, flicker.width, flicker.height, -1, 1);
891+ movementSpy.wait();
892+ }
893+ function test_flick_pressTimeout() {
894+ flick(flicker, 0, 0, flicker.width, flicker.height, 400);
895+ movementSpy.wait();
896+ }
897+ function test_flick_pressTimeout_short() {
898+ flick(flicker, flicker.width, flicker.height, -flicker.width, -flicker.height, 400, 1);
899+ movementSpy.wait();
900+ }
901+ function test_flick_pressTimeout_long() {
902+ flick(flicker, flicker.width, flicker.height, -flicker.width, -flicker.height, 400, 100);
903+ movementSpy.wait();
904+ }
905 }
906 }

Subscribers

People subscribed via source and target branches

to status/vote changes: