Merge lp:~nik90/ubuntu-clock-app/add-world-qml-tests into lp:ubuntu-clock-app

Proposed by Nekhelesh Ramananthan
Status: Superseded
Proposed branch: lp:~nik90/ubuntu-clock-app/add-world-qml-tests
Merge into: lp:ubuntu-clock-app
Diff against target: 809 lines (+518/-74)
11 files modified
app/alarm/AlarmList.qml (+1/-1)
app/alarm/EditAlarmPage.qml (+3/-0)
app/worldclock/WorldCityList.qml (+3/-3)
debian/changelog (+3/-0)
tests/autopilot/ubuntu_clock_app/emulators.py (+9/-5)
tests/unit/CMakeLists.txt (+9/-0)
tests/unit/MockClockApp.qml (+88/-0)
tests/unit/Utils.qml (+89/-0)
tests/unit/tst_alarm.qml (+114/-56)
tests/unit/tst_alarmLabel.qml (+5/-9)
tests/unit/tst_worldClock.qml (+194/-0)
To merge this branch: bzr merge lp:~nik90/ubuntu-clock-app/add-world-qml-tests
Reviewer Review Type Date Requested Status
Ubuntu Clock Developers Pending
Review via email: mp+238216@code.launchpad.net

Commit message

Added world clock feature qml tests.

Description of the change

Added world clock feature qml tests.

The QML Test Suite now comprises of Feature, Unit and Integration tests and collectively has a far higher test coverage of the clock app than AP test have. A few more MPs later, I might propose removing AP tests.

To post a comment you must log in.
160. By Nekhelesh Ramananthan

merged trunk

161. By Nekhelesh Ramananthan

Migrated tst_worldClock over to ClockTestCase

162. By Nekhelesh Ramananthan

renamed confirmWorldCityAddition() to assertWorldCityAddition()

163. By Nekhelesh Ramananthan

Removed unnecessary confirm statement iat the start of a test

164. By Nekhelesh Ramananthan

Added TODO comment for mocking the searchOnline function

165. By Nekhelesh Ramananthan

Improved if logic in emulators.py

166. By Nekhelesh Ramananthan

Simplified code a bit

167. By Nekhelesh Ramananthan

Merged prerequisite branch

168. By Nekhelesh Ramananthan

Merged prerequisite branch

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'app/alarm/AlarmList.qml'
2--- app/alarm/AlarmList.qml 2014-10-05 15:33:27 +0000
3+++ app/alarm/AlarmList.qml 2014-10-13 20:56:20 +0000
4@@ -129,7 +129,7 @@
5
6 else {
7 pageStack.push(Qt.resolvedUrl("EditAlarmPage.qml"),
8- {"isNewAlarm": false, "alarmIndex": index})
9+ {isNewAlarm: false, alarmIndex: index, alarmModel: alarmModel})
10 }
11 }
12
13
14=== modified file 'app/alarm/EditAlarmPage.qml'
15--- app/alarm/EditAlarmPage.qml 2014-10-10 19:58:49 +0000
16+++ app/alarm/EditAlarmPage.qml 2014-10-13 20:56:20 +0000
17@@ -37,6 +37,9 @@
18 // Temporary alarm used to read saved alarm and modify them
19 property var tempAlarm
20
21+ // Property to store the alarm model
22+ property var alarmModel
23+
24 title: isNewAlarm ? i18n.tr("New alarm") : i18n.tr("Edit alarm")
25 visible: false
26
27
28=== modified file 'app/worldclock/WorldCityList.qml'
29--- app/worldclock/WorldCityList.qml 2014-10-10 10:55:27 +0000
30+++ app/worldclock/WorldCityList.qml 2014-10-13 20:56:20 +0000
31@@ -251,7 +251,7 @@
32
33 delegate: ListItem.Base {
34 showDivider: false
35- objectName: "worldCityItem" + index
36+ objectName: "defaultWorldCityItem" + index
37
38 Column {
39 id: worldCityDelegateColumn
40@@ -265,7 +265,7 @@
41
42 Label {
43 text: city
44- objectName: "cityNameText"
45+ objectName: "defaultCityNameText"
46 width: parent.width
47 elide: Text.ElideRight
48 color: UbuntuColors.midAubergine
49@@ -273,7 +273,7 @@
50
51 Label {
52 text: country
53- objectName: "countryNameText"
54+ objectName: "defaultCountryNameText"
55 fontSize: "xx-small"
56 width: parent.width
57 elide: Text.ElideRight
58
59=== modified file 'debian/changelog'
60--- debian/changelog 2014-10-11 11:46:39 +0000
61+++ debian/changelog 2014-10-13 20:56:20 +0000
62@@ -12,6 +12,9 @@
63 * Synced ListItemWithActions with upstream
64 * Delayed loading of AlarmModel to improve app startup time (LP: #1362140)
65 * Fixed alarm page header width warning and corrected icon spacing.
66+ * Added edit alarm qml tests and added a library helper which contains commonly
67+ used test functions to avoid code duplication in future tests.
68+ * Added world clock feature qml tests
69
70 [Akiva Shammai Avraham]
71 * Improved the analog clock performance by updating the clock hands every second
72
73=== modified file 'tests/autopilot/ubuntu_clock_app/emulators.py'
74--- tests/autopilot/ubuntu_clock_app/emulators.py 2014-10-10 22:12:50 +0000
75+++ tests/autopilot/ubuntu_clock_app/emulators.py 2014-10-13 20:56:20 +0000
76@@ -267,14 +267,18 @@
77
78 for index in range(int(cityList.count)):
79 if cityList.wait_select_single(
80- objectName="worldCityItem{}".format(index)).wait_select_single(
81- "Label", objectName="cityNameText").text == city_Name:
82+ objectName="defaultWorldCityItem{}".format(index)).\
83+ wait_select_single(
84+ "Label",
85+ objectName="defaultCityNameText").text == city_Name:
86 if cityList.wait_select_single(
87- objectName="worldCityItem{}".format(index)).\
88- wait_select_single("Label", objectName="countryNameText").\
89+ objectName="defaultWorldCityItem{}".format(index)).\
90+ wait_select_single(
91+ "Label",
92+ objectName="defaultCountryNameText").\
93 text == country_Name:
94 cityList.click_element(
95- "worldCityItem{}".format(index), direction=None)
96+ "defaultWorldCityItem{}".format(index), direction=None)
97 break
98
99 @autopilot_logging.log_action(logger.info)
100
101=== modified file 'tests/unit/CMakeLists.txt'
102--- tests/unit/CMakeLists.txt 2014-10-05 21:22:25 +0000
103+++ tests/unit/CMakeLists.txt 2014-10-13 20:56:20 +0000
104@@ -26,6 +26,7 @@
105 declare_qml_test("Alarm" tst_alarm.qml)
106 declare_qml_test("AlarmSound" tst_alarmSound.qml)
107 declare_qml_test("AlarmUtils" tst_alarmUtils.qml)
108+ declare_qml_test("WorldClock" tst_worldClock.qml)
109 else()
110 if (NOT QMLTESTRUNNER_BIN)
111 message(WARNING "Qml tests disabled: qmltestrunner not found")
112@@ -40,5 +41,13 @@
113 tst_alarm.qml
114 tst_alarmSound.qml
115 tst_alarmUtils.qml
116+ tst_worldClock.qml
117 )
118 add_custom_target(tst_QmlFiles ALL SOURCES ${QML_TST_FILES})
119+
120+set(QML_TST_UTILS
121+ Utils.qml
122+ MockClockApp.qml
123+)
124+
125+add_custom_target(tst_Utils ALL SOURCES ${QML_TST_UTILS})
126
127=== added file 'tests/unit/MockClockApp.qml'
128--- tests/unit/MockClockApp.qml 1970-01-01 00:00:00 +0000
129+++ tests/unit/MockClockApp.qml 2014-10-13 20:56:20 +0000
130@@ -0,0 +1,88 @@
131+/*
132+ * Copyright (C) 2014 Canonical Ltd
133+ *
134+ * This file is part of Ubuntu Clock App
135+ *
136+ * Ubuntu Clock App is free software: you can redistribute it and/or modify
137+ * it under the terms of the GNU General Public License version 3 as
138+ * published by the Free Software Foundation.
139+ *
140+ * Ubuntu Clock App is distributed in the hope that it will be useful,
141+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
142+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
143+ * GNU General Public License for more details.
144+ *
145+ * You should have received a copy of the GNU General Public License
146+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
147+ */
148+
149+import QtQuick 2.3
150+import DateTime 1.0
151+import U1db 1.0 as U1db
152+import Ubuntu.Components 1.1
153+import "../../app/clock"
154+
155+/*
156+ This file is meant to create a fake but fully fleshed clock app with its
157+ own database and settings. This will avoid messing with the user data while
158+ running the tests.
159+*/
160+
161+MainView {
162+ id: clockApp
163+
164+ // Property to store the state of an application (active or suspended)
165+ property bool applicationState: Qt.application.active
166+
167+ width: units.gu(40)
168+ height: units.gu(70)
169+ useDeprecatedToolbar: false
170+ applicationName: "com.ubuntu.fakeclock.test"
171+
172+ U1db.Database {
173+ id: clockDB
174+ path: "user-preferences"
175+ }
176+
177+ U1db.Document {
178+ id: clockModeDocument
179+ create: true
180+ database: clockDB
181+ docId: "clockModeDocument"
182+ defaults: { "digitalMode": false }
183+ }
184+
185+ DateTime {
186+ id: localTimeSource
187+ updateInterval: 1000
188+ }
189+
190+ PageStack {
191+ id: mainStack
192+ objectName: "pageStack"
193+
194+ Component.onCompleted: push(clockPage)
195+
196+ ClockPage {
197+ id: clockPage
198+
199+ Loader {
200+ id: alarmModelLoader
201+ asynchronous: false
202+ }
203+
204+ alarmModel: alarmModelLoader.item
205+ bottomEdgeEnabled: alarmModelLoader.status === Loader.Ready
206+ clockTime: new Date
207+ (
208+ localTimeSource.localDateString.split(":")[0],
209+ localTimeSource.localDateString.split(":")[1]-1,
210+ localTimeSource.localDateString.split(":")[2],
211+ localTimeSource.localTimeString.split(":")[0],
212+ localTimeSource.localTimeString.split(":")[1],
213+ localTimeSource.localTimeString.split(":")[2],
214+ localTimeSource.localTimeString.split(":")[3]
215+ )
216+ }
217+ }
218+}
219
220=== added file 'tests/unit/Utils.qml'
221--- tests/unit/Utils.qml 1970-01-01 00:00:00 +0000
222+++ tests/unit/Utils.qml 2014-10-13 20:56:20 +0000
223@@ -0,0 +1,89 @@
224+/*
225+ * Copyright (C) 2014 Canonical Ltd
226+ *
227+ * This file is part of Ubuntu Clock App
228+ *
229+ * Ubuntu Clock App is free software: you can redistribute it and/or modify
230+ * it under the terms of the GNU General Public License version 3 as
231+ * published by the Free Software Foundation.
232+ *
233+ * Ubuntu Clock App is distributed in the hope that it will be useful,
234+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
235+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
236+ * GNU General Public License for more details.
237+ *
238+ * You should have received a copy of the GNU General Public License
239+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
240+ */
241+
242+import QtTest 1.0
243+import QtQuick 2.3
244+import Ubuntu.Test 1.0
245+
246+/*
247+ Utils.qml includes a set of commonly used test functions like pressing header
248+ buttons and helps reduce code duplication.
249+
250+ Usage:
251+ Utils {
252+ id: testUtils
253+ }
254+
255+ UbuntuTestCase {
256+ id: sampleTest
257+ name: "SampleTest"
258+
259+ when: windowShown
260+
261+ function initTestCase() {
262+ header = findChild(mainView, "MainView_Header")
263+ backButton = findChild(alarmTest.header, "customBackButton")
264+ }
265+
266+ function test_something() {
267+ testUtils._pressHeaderButton(header, "addAlarmAction")
268+ }
269+ }
270+*/
271+
272+UbuntuTestCase {
273+ id: testUtils
274+
275+ function pressHeaderButton(header, objectName) {
276+ var headerButton = findChild(header, objectName + "_header_button")
277+ mouseClick(headerButton, centerOf(headerButton).x, centerOf(headerButton).y)
278+ }
279+
280+ function pressButton(objectName) {
281+ mouseClick(objectName, centerOf(objectName).x, centerOf(objectName).y)
282+ }
283+
284+ function getPage(pageStack, objectName) {
285+ var page = findChild(pageStack, objectName)
286+ waitForRendering(page)
287+ return page
288+ }
289+
290+ function swipeToDeleteItem(item)
291+ {
292+ var startX = item.threshold
293+ var startY = item.height / 2
294+ var endX = item.width
295+ var endY = startY
296+ mousePress(item, startX, startY)
297+ mouseMoveSlowly(item,
298+ startX, startY,
299+ endX - startX, endY - startY,
300+ 10, 100)
301+ mouseRelease(item, endX, endY)
302+ mouseClick(item, startX, startY)
303+ }
304+
305+ function clearTextField(textfield) {
306+ // Get textfield focus by clicking once
307+ mouseClick(textfield, textfield.width - units.gu(2), centerOf(textfield).y)
308+
309+ // Click on the clear button shown on the right
310+ mouseClick(textfield, textfield.width - units.gu(2), centerOf(textfield).y)
311+ }
312+}
313
314=== modified file 'tests/unit/tst_alarm.qml'
315--- tests/unit/tst_alarm.qml 2014-10-10 21:24:28 +0000
316+++ tests/unit/tst_alarm.qml 2014-10-13 20:56:20 +0000
317@@ -63,6 +63,10 @@
318 id: alarmPage
319 }
320
321+ Utils {
322+ id: utils
323+ }
324+
325 UbuntuTestCase {
326 id: alarmTest
327 name: "AlarmTest"
328@@ -79,31 +83,11 @@
329
330 // ************* Helper Functions ************
331
332- function _pressAddAlarmHeaderButton() {
333- var addButton = findChild(header, "addAlarmAction" + "_header_button")
334- mouseClick(addButton, centerOf(addButton).x, centerOf(addButton).y)
335- }
336-
337- function _pressSaveAlarmHeaderButton() {
338- var saveButton = findChild(alarmTest.header, "saveAlarmAction" + "_header_button")
339- mouseClick(saveButton, centerOf(saveButton).x, centerOf(saveButton).y)
340- }
341-
342- function _pressBackButton() {
343- mouseClick(backButton, centerOf(backButton).x, centerOf(backButton).y)
344- }
345-
346 function _pressListItem(page, objectName) {
347 var listitem = findChild(page, objectName)
348 mouseClick(listitem, centerOf(listitem).x, centerOf(listitem).y)
349 }
350
351- function _getPage(objectName) {
352- var page = findChild(pageStack, objectName)
353- waitForRendering(page)
354- return page
355- }
356-
357 function _waitForPickerToStopMoving(picker) {
358 waitForRendering(picker);
359 tryCompareFunction(function(){return picker.moving}, false);
360@@ -112,7 +96,6 @@
361 function _setAlarmTime(picker, time) {
362 picker.date = time
363 _waitForPickerToStopMoving(picker)
364- return picker.date
365 }
366
367 function _setAlarmRepeatDays(alarmRepeatPage, days) {
368@@ -136,8 +119,7 @@
369
370 function _setAlarmLabel(alarmLabelPage, label) {
371 var alarmLabel = findChild(alarmLabelPage, "labelEntry")
372- mouseClick(alarmLabel, alarmLabel.width - units.gu(2), centerOf(alarmLabel).y)
373- mouseClick(alarmLabel, alarmLabel.width - units.gu(2), centerOf(alarmLabel).y)
374+ utils.clearTextField(alarmLabel)
375 typeString(label)
376 }
377
378@@ -173,19 +155,9 @@
379 }
380 }
381
382- function _swipeToDeleteItem(item)
383- {
384- var startX = item.threshold
385- var startY = item.height / 2
386- var endX = item.width
387- var endY = startY
388- mousePress(item, startX, startY)
389- mouseMoveSlowly(item,
390- startX, startY,
391- endX - startX, endY - startY,
392- 10, 100)
393- mouseRelease(item, endX, endY)
394- mouseClick(item, startX, startY)
395+ function _confirmListItemValue(page, objectName, expectedValue, message) {
396+ var listitem = findChild(page, objectName)
397+ compare(listitem.subText, expectedValue, message)
398 }
399
400 function _deleteAlarm(label, repeat, time, status) {
401@@ -196,50 +168,104 @@
402 var alarmObject = findChild(alarmsList, "alarm"+index)
403
404 if (index !== -1) {
405- _swipeToDeleteItem(alarmObject)
406+ utils.swipeToDeleteItem(alarmObject)
407 }
408
409 tryCompare(alarmsList, "count", oldCount-1, 10000, "Alarm count did not decrease after deleting the alarm")
410 }
411
412 function _setAlarm(label, repeat, time) {
413- _pressAddAlarmHeaderButton()
414+ utils.pressHeaderButton(header, "addAlarmAction")
415
416 var addAlarmPage = findChild(pageStack, "AddAlarmPage")
417 waitForRendering(addAlarmPage)
418
419+ // Set the alarm time
420 var alarmTimePicker = findChild(pageStack, "alarmTime")
421- var date = _setAlarmTime(alarmTimePicker, time)
422+ _setAlarmTime(alarmTimePicker, time)
423
424+ // Set the alarm repeat options
425 _pressListItem(addAlarmPage, "alarmRepeat")
426- var alarmRepeatPage = _getPage("alarmRepeatPage")
427+ var alarmRepeatPage = utils.getPage(pageStack, "alarmRepeatPage")
428 _setAlarmRepeatDays(alarmRepeatPage, repeat)
429- _pressBackButton()
430+ utils.pressButton(backButton)
431
432 waitForRendering(addAlarmPage)
433
434+ // Set the alarm label
435 _pressListItem(addAlarmPage, "alarmLabel")
436- var alarmLabelPage = _getPage("alarmLabelPage")
437+ var alarmLabelPage = utils.getPage(pageStack, "alarmLabelPage")
438 _setAlarmLabel(alarmLabelPage, label)
439- _pressBackButton()
440-
441- waitForRendering(addAlarmPage)
442-
443- _pressListItem(addAlarmPage, "alarmSound")
444- var alarmSoundPage = _getPage("alarmSoundPage")
445- _setAlarmSound(alarmSoundPage)
446- _pressBackButton()
447-
448- waitForRendering(addAlarmPage)
449-
450- _pressSaveAlarmHeaderButton()
451+ utils.pressButton(backButton)
452+
453+ waitForRendering(addAlarmPage)
454+
455+ // Set the alarm sound
456+ _pressListItem(addAlarmPage, "alarmSound")
457+ var alarmSoundPage = utils.getPage(pageStack, "alarmSoundPage")
458+ _setAlarmSound(alarmSoundPage)
459+ utils.pressButton(backButton)
460+
461+ waitForRendering(addAlarmPage)
462+
463+ utils.pressHeaderButton(header, "saveAlarmAction")
464+
465+ waitForRendering(alarmPage)
466+ }
467+
468+ function _editAlarm(oldlabel, oldrepeat, oldtime, status, newlabel, newrepeat, newtime) {
469+ // Find the index of the alarm which needs to be edited
470+ var alarmIndex = findAlarm(oldlabel, oldrepeat, oldtime, status)
471+
472+ if (alarmIndex === -1) {
473+ fail("Cannot find saved alarm to edit")
474+ }
475+
476+ // Press the alarm to be edited
477+ var alarmsList = findChild(alarmPage, "alarmListView")
478+ var alarmObject = findChild(alarmsList, "alarm"+alarmIndex)
479+ mouseClick(alarmObject, centerOf(alarmObject).x, centerOf(alarmObject).y)
480+
481+ // Proceed to verify the alarm read is correct and then set new values
482+ var addAlarmPage = findChild(pageStack, "AddAlarmPage")
483+ waitForRendering(addAlarmPage)
484+
485+ var alarmTimePicker = findChild(pageStack, "alarmTime")
486+ compare(Qt.formatTime(alarmTimePicker.date), oldtime, "Time read from the saved alarm is incorrect")
487+ _setAlarmTime(alarmTimePicker, newtime)
488+
489+ _confirmListItemValue(addAlarmPage, "alarmRepeat", oldrepeat, "Alarm repeat options read from the saved alarm is incorrect")
490+ _pressListItem(addAlarmPage, "alarmRepeat")
491+ var alarmRepeatPage = utils.getPage(pageStack, "alarmRepeatPage")
492+ _setAlarmRepeatDays(alarmRepeatPage, newrepeat)
493+ utils.pressButton(backButton)
494+
495+ waitForRendering(addAlarmPage)
496+
497+ _confirmListItemValue(addAlarmPage, "alarmLabel", oldlabel, "Alarm name read from the saved alarm is incorrect")
498+ _pressListItem(addAlarmPage, "alarmLabel")
499+ var alarmLabelPage = utils.getPage(pageStack, "alarmLabelPage")
500+ _setAlarmLabel(alarmLabelPage, newlabel)
501+ utils.pressButton(backButton)
502+
503+ waitForRendering(addAlarmPage)
504+
505+ _confirmListItemValue(addAlarmPage, "alarmSound", "Celestial", "Alarm sound read from the saved alarm is incorrect")
506+ _pressListItem(addAlarmPage, "alarmSound")
507+ var alarmSoundPage = utils.getPage(pageStack, "alarmSoundPage")
508+ _setAlarmSound(alarmSoundPage)
509+ utils.pressButton(backButton)
510+
511+ waitForRendering(addAlarmPage)
512+
513+ utils.pressHeaderButton(header, "saveAlarmAction")
514
515 waitForRendering(alarmPage)
516 }
517
518 // ************* Test Functions ************
519
520- function test_createAlarm_data() {
521+ function test_01_createAlarm_data() {
522 return [
523 {tag: "Weekday Alarms", name: "Weekday Alarm", repeat: [0,1,2,3,4], repeatLabel: "Weekdays"},
524 {tag: "Weekend Alarms", name: "Weekend Alarm", repeat: [5,6], repeatLabel: "Weekends"},
525@@ -248,7 +274,7 @@
526 }
527
528 // Test to check if creating an alarm works as expected
529- function test_createAlarm(data) {
530+ function test_01_createAlarm(data) {
531 var date = new Date()
532 date.setHours((date.getHours() + 10) % 24)
533 date.setMinutes((date.getMinutes() + 40) % 60)
534@@ -263,5 +289,37 @@
535 */
536 _deleteAlarm(data.name, data.repeatLabel, Qt.formatTime(date), true)
537 }
538+
539+ // Test to check if editing an alarm and saving it works as expected
540+ function test_02_editAlarm() {
541+ var date = new Date()
542+ date.setHours((date.getHours() + 10) % 24)
543+ date.setMinutes((date.getMinutes() + 40) % 60)
544+ date.setSeconds(0)
545+
546+ _setAlarm("Test Edit Alarm", [0,1,2,3,4], date)
547+
548+ var newDate = new Date()
549+ newDate.setHours((newDate.getHours() + 5) % 24)
550+ newDate.setMinutes((newDate.getMinutes() + 15) % 60)
551+ newDate.setSeconds(0)
552+
553+ _editAlarm("Test Edit Alarm", "Weekdays", Qt.formatTime(date), true, "Alarm Edited", [5,6], newDate)
554+
555+ /*
556+ #NOTE: This wait is required since as per the design after an alarm is edited and saved
557+ it shows the remaining time to that alarm and then after 5 secs shows the alarm
558+ frequency. Hence we need to wait for 5 seconds before confirming alarm creation.
559+ */
560+ wait(6000)
561+
562+ _confirmAlarmCreation("Alarm Edited", "Weekends", Qt.formatTime(newDate), true)
563+
564+ /*
565+ #FIXME: This won't be required once we mock up alarm data. Until
566+ then we need to delete alarms to cleanup after the tests.
567+ */
568+ _deleteAlarm("Alarm Edited", "Weekends", Qt.formatTime(newDate), true)
569+ }
570 }
571 }
572
573=== modified file 'tests/unit/tst_alarmLabel.qml'
574--- tests/unit/tst_alarmLabel.qml 2014-09-25 11:14:24 +0000
575+++ tests/unit/tst_alarmLabel.qml 2014-10-13 20:56:20 +0000
576@@ -38,6 +38,10 @@
577 alarm: _alarm
578 }
579
580+ Utils {
581+ id: utils
582+ }
583+
584 UbuntuTestCase {
585 id: alarmLabelPageTest
586 name: "AlarmLabelPage"
587@@ -55,14 +59,6 @@
588 backButton = findChild(header, "customBackButton")
589 }
590
591- function clearTextField(textfield) {
592- // Get textfield focus by clicking once
593- mouseClick(textfield, textfield.width - units.gu(2), textfield.height/2)
594-
595- // Click on the clear button shown on the right
596- mouseClick(textfield, textfield.width - units.gu(2), textfield.height/2)
597- }
598-
599 /*
600 Test to check if the alarm label has focus true by default to ensure
601 that the OSK is shown when the opens the alarm label page.
602@@ -87,7 +83,7 @@
603 compare(alarmLabel.text, "Alarm", "Default alarm label is not Alarm")
604 compare(backButton.enabled, true, "Back header button is not enabled by default")
605
606- clearTextField(alarmLabel)
607+ utils.clearTextField(alarmLabel)
608 typeString(data.string)
609
610 compare(alarmLabel.text, data.string, "Alarm label is not what was type in the textfield")
611
612=== added file 'tests/unit/tst_worldClock.qml'
613--- tests/unit/tst_worldClock.qml 1970-01-01 00:00:00 +0000
614+++ tests/unit/tst_worldClock.qml 2014-10-13 20:56:20 +0000
615@@ -0,0 +1,194 @@
616+/*
617+ * Copyright (C) 2014 Canonical Ltd
618+ *
619+ * This file is part of Ubuntu Clock App
620+ *
621+ * Ubuntu Clock App is free software: you can redistribute it and/or modify
622+ * it under the terms of the GNU General Public License version 3 as
623+ * published by the Free Software Foundation.
624+ *
625+ * Ubuntu Clock App is distributed in the hope that it will be useful,
626+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
627+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
628+ * GNU General Public License for more details.
629+ *
630+ * You should have received a copy of the GNU General Public License
631+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
632+ */
633+
634+import QtQuick 2.0
635+import QtTest 1.0
636+import Ubuntu.Test 1.0
637+import Ubuntu.Components 1.1
638+
639+MockClockApp {
640+ id: clockApp
641+
642+ Utils {
643+ id: utils
644+ }
645+
646+ UbuntuTestCase {
647+ id: worldClockFeatureTest
648+ name: "WorldClockFeatureTest"
649+
650+ when: windowShown
651+
652+ property var header
653+ property var backButton
654+ property var clockPage
655+ property var pageStack
656+
657+ function initTestCase() {
658+ header = findChild(clockApp, "MainView_Header")
659+ backButton = findChild(header, "customBackButton")
660+ pageStack = findChild(clockApp, "pageStack")
661+ clockPage = findChild(clockApp, "clockPage")
662+ }
663+
664+ // *********** Helper Functions ************
665+
666+ function _pressAddWorldCityButton() {
667+ var addWorldCityButton = findChild(clockApp, "addWorldCityButton")
668+ utils.pressButton(addWorldCityButton)
669+ }
670+
671+ function _findWorldCity(cityList, type, cityName, countryName) {
672+ /*
673+ The list view for the user world city list and the available world
674+ city list have the same structure with some minor object name
675+ changes. The 'objectPrefix' varible is used to handle that.
676+ */
677+ var objectPrefix = type === "user" ? "user" : "default"
678+
679+ for(var i=0; i<cityList.count; i++) {
680+ var cityListItem = findChild(clockApp, objectPrefix+"WorldCityItem"+i)
681+ var city = findChild(cityListItem, objectPrefix+"CityNameText")
682+ var country = findChild(cityListItem, objectPrefix+"CountryNameText")
683+
684+ if (city.text === cityName && country.text === countryName) {
685+ return i
686+ }
687+ }
688+
689+ return -1;
690+ }
691+
692+ function _confirmWorldCityAddition(cityName, countryName) {
693+ var cityList = findChild(clockApp, "userWorldCityRepeater")
694+
695+ /*
696+ Confirm that at least one world city is saved before proceeding
697+ to check if that's the city added during the test.
698+ */
699+ tryCompareFunction(function() { return cityList.count > 0}, true)
700+
701+ var cityIndex = _findWorldCity(cityList, "user", cityName, countryName)
702+
703+ if (cityIndex === -1) {
704+ // If city couldn't be found in the saved city list, fail the test
705+ fail("City added during the test cannot be found in the user world city list!")
706+ }
707+ }
708+
709+ function _deleteWorldCity(cityName, countryName) {
710+ var cityList = findChild(clockApp, "userWorldCityRepeater")
711+
712+ /*
713+ Confirm that at least one world city is saved before proceeding
714+ to delete the city added during the test.
715+ */
716+ tryCompareFunction(function() { return cityList.count > 0}, true)
717+
718+ var oldCount = cityList.count
719+ var cityIndex = _findWorldCity(cityList, "user", cityName, countryName)
720+
721+ if (cityIndex === -1) {
722+ fail("City added during the test cannot be found in the user world city list!")
723+ }
724+ else {
725+ var cityListItem = findChild(clockApp, "userWorldCityItem"+cityIndex)
726+ utils.swipeToDeleteItem(cityListItem)
727+ }
728+
729+ /*
730+ #FIXME: Commented out the following line as deleting a world city
731+ when there is only one world city does not decrease the count to 0
732+ but leaves it as 1 causing the test to fail. This has been reported
733+ in bug #1368393. (Also fails in Autopilot)
734+
735+ tryCompare(cityList, "count", oldCount-1, 5000, "city list count did not decrease")
736+
737+ The wait() call below is to ensure that the world city is deleted properly
738+ which wouldn't be required if could do the count decrease check mentioned above.
739+ */
740+
741+ wait(1000)
742+ }
743+
744+ function _addCityFromList(cityName, countryName) {
745+ var worldCityPage = utils.getPage(pageStack, "worldCityList")
746+ var cityList = findChild(worldCityPage, "cityList")
747+
748+ // Wait for the list to be populated with results
749+ tryCompareFunction(function() { return cityList.count > 0}, true)
750+
751+ var cityIndex = _findWorldCity(cityList, "default", cityName, countryName)
752+
753+ if (cityIndex === -1) {
754+ fail("City cannot be found in the local world city list")
755+ }
756+
757+ var cityListItem = findChild(cityList, "defaultWorldCityItem"+cityIndex)
758+ mouseClick(cityListItem, centerOf(cityListItem).x, centerOf(cityListItem).y)
759+ }
760+
761+ function _addCityBySearchingOnline(cityName, countryName) {
762+ utils.pressHeaderButton(header, "searchButton")
763+ var searchField = findChild(clockApp, "searchField")
764+ tryCompare(searchField, "visible", true, 5000, "Search field is not visible")
765+ typeString(cityName)
766+ _addCityFromList(cityName, countryName)
767+ }
768+
769+ // *********** Test Functions *************
770+
771+ /*
772+ Test to check if a city found in the world city list can be added
773+ to the user world city list.
774+ */
775+ function test_addCityAlreadyPresentInWorldCityList() {
776+ var clockPage = utils.getPage(pageStack, "clockPage")
777+
778+ _pressAddWorldCityButton()
779+
780+ var worldCityPage = utils.getPage(pageStack, "worldCityList")
781+ waitForRendering(worldCityPage)
782+
783+ _addCityFromList("Amsterdam", "Netherlands")
784+ _confirmWorldCityAddition("Amsterdam", "Netherlands")
785+
786+ // Clean up after the test by deleting the city which was added during the test
787+ _deleteWorldCity("Amsterdam", "Netherlands")
788+ }
789+
790+ /*
791+ Test to check if a city now found in the world city list can be added
792+ by searcing it online and then adding it from the results returned.
793+ */
794+ function test_addCityBySearchingOnline() {
795+ var clockPage = utils.getPage(pageStack, "clockPage")
796+
797+ _pressAddWorldCityButton()
798+
799+ var worldCityPage = utils.getPage(pageStack, "worldCityList")
800+ waitForRendering(worldCityPage)
801+
802+ _addCityBySearchingOnline("Venice", "Provincia di Venezia, Veneto, Italy")
803+ _confirmWorldCityAddition("Venice", " Veneto, Italy")
804+
805+ // Clean up after the test by deleting the city which was added during the test
806+ _deleteWorldCity("Venice", " Veneto, Italy")
807+ }
808+ }
809+}

Subscribers

People subscribed via source and target branches