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

Proposed by Nekhelesh Ramananthan
Status: Merged
Approved by: Nekhelesh Ramananthan
Approved revision: 168
Merged at revision: 147
Proposed branch: lp:~nik90/ubuntu-clock-app/add-world-qml-tests
Merge into: lp:ubuntu-clock-app
Prerequisite: lp:~nik90/ubuntu-clock-app/edit-alarm-qml-tests
Diff against target: 417 lines (+309/-23)
6 files modified
app/worldclock/WorldCityList.qml (+3/-3)
debian/changelog (+1/-0)
tests/autopilot/ubuntu_clock_app/emulators.py (+20/-20)
tests/unit/CMakeLists.txt (+3/-0)
tests/unit/MockClockApp.qml (+88/-0)
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
Leo Arias (community) Approve
Ubuntu Phone Apps Jenkins Bot continuous-integration Approve
Ubuntu Clock Developers Pending
Review via email: mp+238217@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.
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 :
Download full text (3.2 KiB)

You have a couple of ifs there that are really hard to understand.
You can refactor them like this: http://paste.ubuntu.com/8556979/
(I haven't run the tests with the refactor, so please double check the code, I could make typos).

Also, please remember that on python, we should name the variables with all lower case separating words with spaces. And that we should prefer single quotes instead of double quotes. Looking at the emulators file, I see some style errors. They can be fixed in a separate branch, unless you are planning to kill that file soon.

126 +/*
127 + This file is meant to create a fake but fully fleshed clock app with its
128 + own database and settings. This will avoid messing with the user data while
129 + running the tests.
130 +*/

Interesting, I like it. You just need to take a lot of care that this test double is as close to the real as possible. Ideally without duplicating any code, because otherwise they will be hard to maintain. Usually, devs add things to the real one and forget to update the double, so they end up testing a different thing.

Could you make a QML file that takes the app name and any other things you want to change on the mock as parameters, and then make both app/ubuntu-clock-app.qml and tests/unit/MockClockApp.qml extend that file?

250 + function _findWorldCity(cityList, type, cityName, countryName) {

It's slightly clearer when you make two methods instead of passing a type argument:
findUserWorldCity and findDefaultWorldCity.
Those are the methods you call from a test. Then, you make them call an internal _findWorldCity where you pass the right prefix. But you are encapsulating the prefix in the internal methods, your tests don't know about the exact prefix. So by changing the tests to call a method instead of passing a string, it will be easier for you if you ever have to change the prefix. Instead of changing it in all the tests that call findWorldCity, you will just have to change it on the non-internal methods and the name can remain the same.

271 + function _confirmWorldCityAddition(cityName, countryName) {

Here again, I prefer assert. confirm sounds like a step of the test, like confirm a dialog or something like that.

295 + tryCompareFunction(function() { return cityList.count > 0}, true)

And here again, this shouldn't be needed if you are already asserting the successful creation during a test.

327 + // Wait for the list to be populated with results
328 + tryCompareFunction(function() { return cityList.count > 0}, true)

Now this is a valid usage of an assertion on the middle of the steps. But it's just because this framework doesn't have a proper wait. On autopilot we would do it with a wait_for or something similar, that's a little different than an assertion.

373 + function test_addCityBySearchingOnline() {

You have to be careful here. The unit tests many times are run in a confined machine without internet access. As the tests are passing, I'm guessing that's not the case for the jenkins runners. But ideally, you would replace the online model with a hard-coded one for a unit test. And then do an integration test for the service that provides you with cities.

This is great, ...

Read more...

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

Revision history for this message
Nekhelesh Ramananthan (nik90) wrote :
Download full text (3.2 KiB)

> You have a couple of ifs there that are really hard to understand.
> You can refactor them like this: http://paste.ubuntu.com/8556979/
> (I haven't run the tests with the refactor, so please double check the code, I
> could make typos).
>
> Also, please remember that on python, we should name the variables with all
> lower case separating words with spaces. And that we should prefer single
> quotes instead of double quotes. Looking at the emulators file, I see some
> style errors. They can be fixed in a separate branch, unless you are planning
> to kill that file soon.

Thnx I fixed that as well. I was only planning to make minimal changes to emulators.py in fear of breaking the AP test ;). But now the if logic looks much simpler despite taking me longer than usual to fix that (hence my uneasiness in touch python code)

> 250 + function _findWorldCity(cityList, type, cityName, countryName) {
>
> It's slightly clearer when you make two methods instead of passing a type
> argument:
> findUserWorldCity and findDefaultWorldCity.
> Those are the methods you call from a test. Then, you make them call an
> internal _findWorldCity where you pass the right prefix. But you are
> encapsulating the prefix in the internal methods, your tests don't know about
> the exact prefix. So by changing the tests to call a method instead of passing
> a string, it will be easier for you if you ever have to change the prefix.
> Instead of changing it in all the tests that call findWorldCity, you will just
> have to change it on the non-internal methods and the name can remain the
> same.
>

Done. I hope what I did is what you had in mind as well.

> 271 + function _confirmWorldCityAddition(cityName, countryName) {
>
> Here again, I prefer assert. confirm sounds like a step of the test, like
> confirm a dialog or something like that.

Trivial fix. Done. I will use assert from now on.

>
> 295 + tryCompareFunction(function() { return cityList.count > 0}, true)
>
> And here again, this shouldn't be needed if you are already asserting the
> successful creation during a test.
>

Done

> 327 + // Wait for the list to be populated with results
> 328 + tryCompareFunction(function() { return cityList.count > 0}, true)
>
> Now this is a valid usage of an assertion on the middle of the steps. But it's
> just because this framework doesn't have a proper wait. On autopilot we would
> do it with a wait_for or something similar, that's a little different than an
> assertion.
>

Done

> 373 + function test_addCityBySearchingOnline() {
>
> You have to be careful here. The unit tests many times are run in a confined
> machine without internet access. As the tests are passing, I'm guessing that's
> not the case for the jenkins runners. But ideally, you would replace the
> online model with a hard-coded one for a unit test. And then do an integration
> test for the service that provides you with cities.
>

This is an easy one. I have added a TODO comment about mocking that. I am not sure *yet* how to do this without touching the clock app code which at the moment (for RTM) I don't want to do.

> This is great, as always. Ping me on IRC if you want to ...

Read more...

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

>
> 126 +/*
> 127 + This file is meant to create a fake but fully fleshed clock app with
> its
> 128 + own database and settings. This will avoid messing with the user
> data while
> 129 + running the tests.
> 130 +*/
>
> Interesting, I like it.

This is my first attempt at mocking the clock app. And I was surprised at how easy it was to do this, something which wouldn't be possible with AP without touching the actual app config files.

> You just need to take a lot of care that this test
> double is as close to the real as possible. Ideally without duplicating any
> code, because otherwise they will be hard to maintain. Usually, devs add
> things to the real one and forget to update the double, so they end up testing
> a different thing.

Yup. I agree this can be a potential issue. However this late in the cycle (close to RTM) there wouldn't be any more changes to ubuntu-clock-app.qml. And even if it does, it will be really minor and I will make sure to sync it up to MockClockApp.qml.

>
> Could you make a QML file that takes the app name and any other things you
> want to change on the mock as parameters, and then make both app/ubuntu-clock-
> app.qml and tests/unit/MockClockApp.qml extend that file?
>

At this point, I don't want to avoid touching the ubuntu-clock-app.qml if I can avoid it. I hope that is okay. But I think I have an idea of how you want to proceed with this. I will have another MP which plays with that idea.

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

Merged prerequisite branch

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) :
review: Approve
168. By Nekhelesh Ramananthan

Merged prerequisite branch

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'app/worldclock/WorldCityList.qml'
--- app/worldclock/WorldCityList.qml 2014-10-11 18:39:12 +0000
+++ app/worldclock/WorldCityList.qml 2014-10-14 16:02:15 +0000
@@ -302,7 +302,7 @@
302302
303 delegate: ListItem.Base {303 delegate: ListItem.Base {
304 showDivider: false304 showDivider: false
305 objectName: "worldCityItem" + index305 objectName: "defaultWorldCityItem" + index
306306
307 Column {307 Column {
308 id: worldCityDelegateColumn308 id: worldCityDelegateColumn
@@ -316,7 +316,7 @@
316316
317 Label {317 Label {
318 text: city318 text: city
319 objectName: "cityNameText"319 objectName: "defaultCityNameText"
320 width: parent.width320 width: parent.width
321 elide: Text.ElideRight321 elide: Text.ElideRight
322 color: UbuntuColors.midAubergine322 color: UbuntuColors.midAubergine
@@ -324,7 +324,7 @@
324324
325 Label {325 Label {
326 text: country326 text: country
327 objectName: "countryNameText"327 objectName: "defaultCountryNameText"
328 fontSize: "xx-small"328 fontSize: "xx-small"
329 width: parent.width329 width: parent.width
330 elide: Text.ElideRight330 elide: Text.ElideRight
331331
=== modified file 'debian/changelog'
--- debian/changelog 2014-10-14 16:02:15 +0000
+++ debian/changelog 2014-10-14 16:02:15 +0000
@@ -14,6 +14,7 @@
14 * Fixed alarm page header width warning and corrected icon spacing.14 * Fixed alarm page header width warning and corrected icon spacing.
15 * Added edit alarm qml tests and added a library helper which contains commonly15 * Added edit alarm qml tests and added a library helper which contains commonly
16 used test functions to avoid code duplication in future tests.16 used test functions to avoid code duplication in future tests.
17 * Added world clock feature qml tests
17 * Delayed loading of xmltimezone model until add world city page is loaded and18 * Delayed loading of xmltimezone model until add world city page is loaded and
18 dynamically load/unload the jsontimezone model only when necessary.19 dynamically load/unload the jsontimezone model only when necessary.
1920
2021
=== modified file 'tests/autopilot/ubuntu_clock_app/emulators.py'
--- tests/autopilot/ubuntu_clock_app/emulators.py 2014-10-10 22:12:50 +0000
+++ tests/autopilot/ubuntu_clock_app/emulators.py 2014-10-14 16:02:15 +0000
@@ -133,16 +133,15 @@
133 old_cities_count = self.get_num_of_saved_cities()133 old_cities_count = self.get_num_of_saved_cities()
134 index = 0134 index = 0
135 for index in range(old_cities_count):135 for index in range(old_cities_count):
136 if self.wait_select_single(136 world_city_item = self.wait_select_single(
137 objectName='userWorldCityItem{}'.format(index)).\137 objectName='userWorldCityItem{}'.format(index))
138 wait_select_single("Label", objectName="userCityNameText").\138 city_name_label = world_city_item.wait_select_single(
139 text == city_Name:139 'Label', objectName='userCityNameText')
140 if self.wait_select_single(140 country_name_label = world_city_item.wait_select_single(
141 objectName='userWorldCityItem{}'.format(index)).\141 'Label', objectName='userCountryNameText')
142 wait_select_single(142 if (city_name_label.text == city_Name and
143 "Label", objectName="userCountryNameText").\143 country_name_label.text == country_Name):
144 text == country_Name:144 self._delete_userWorldCityItem(index)
145 self._delete_userWorldCityItem(index)
146145
147 # FIXME -----------------------------------------------------------------146 # FIXME -----------------------------------------------------------------
148 # Commenting the following lines as deleting a world city when there is147 # Commenting the following lines as deleting a world city when there is
@@ -266,16 +265,17 @@
266 cityList.count.wait_for(GreaterThan(0))265 cityList.count.wait_for(GreaterThan(0))
267266
268 for index in range(int(cityList.count)):267 for index in range(int(cityList.count)):
269 if cityList.wait_select_single(268 world_city_item = self.wait_select_single(
270 objectName="worldCityItem{}".format(index)).wait_select_single(269 objectName='defaultWorldCityItem{}'.format(index))
271 "Label", objectName="cityNameText").text == city_Name:270 city_name_label = world_city_item.wait_select_single(
272 if cityList.wait_select_single(271 'Label', objectName='defaultCityNameText')
273 objectName="worldCityItem{}".format(index)).\272 country_name_label = world_city_item.wait_select_single(
274 wait_select_single("Label", objectName="countryNameText").\273 'Label', objectName='defaultCountryNameText')
275 text == country_Name:274 if (city_name_label.text == city_Name and
276 cityList.click_element(275 country_name_label.text == country_Name):
277 "worldCityItem{}".format(index), direction=None)276 cityList.click_element(
278 break277 'defaultWorldCityItem{}'.format(index), direction=None)
278 break
279279
280 @autopilot_logging.log_action(logger.info)280 @autopilot_logging.log_action(logger.info)
281 def search_world_city_(self, city_Name, country_Name):281 def search_world_city_(self, city_Name, country_Name):
282282
=== modified file 'tests/unit/CMakeLists.txt'
--- tests/unit/CMakeLists.txt 2014-10-14 16:02:15 +0000
+++ tests/unit/CMakeLists.txt 2014-10-14 16:02:15 +0000
@@ -26,6 +26,7 @@
26 declare_qml_test("Alarm" tst_alarm.qml)26 declare_qml_test("Alarm" tst_alarm.qml)
27 declare_qml_test("AlarmSound" tst_alarmSound.qml)27 declare_qml_test("AlarmSound" tst_alarmSound.qml)
28 declare_qml_test("AlarmUtils" tst_alarmUtils.qml)28 declare_qml_test("AlarmUtils" tst_alarmUtils.qml)
29 declare_qml_test("WorldClock" tst_worldClock.qml)
29else()30else()
30 if (NOT QMLTESTRUNNER_BIN)31 if (NOT QMLTESTRUNNER_BIN)
31 message(WARNING "Qml tests disabled: qmltestrunner not found")32 message(WARNING "Qml tests disabled: qmltestrunner not found")
@@ -40,10 +41,12 @@
40 tst_alarm.qml41 tst_alarm.qml
41 tst_alarmSound.qml42 tst_alarmSound.qml
42 tst_alarmUtils.qml43 tst_alarmUtils.qml
44 tst_worldClock.qml
43)45)
44add_custom_target(tst_QmlFiles ALL SOURCES ${QML_TST_FILES})46add_custom_target(tst_QmlFiles ALL SOURCES ${QML_TST_FILES})
4547
46set(QML_TST_UTILS48set(QML_TST_UTILS
49 MockClockApp.qml
47 ClockTestCase.qml50 ClockTestCase.qml
48)51)
4952
5053
=== added file 'tests/unit/MockClockApp.qml'
--- tests/unit/MockClockApp.qml 1970-01-01 00:00:00 +0000
+++ tests/unit/MockClockApp.qml 2014-10-14 16:02:15 +0000
@@ -0,0 +1,88 @@
1/*
2 * Copyright (C) 2014 Canonical Ltd
3 *
4 * This file is part of Ubuntu Clock App
5 *
6 * Ubuntu Clock App is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * Ubuntu Clock App is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19import QtQuick 2.3
20import DateTime 1.0
21import U1db 1.0 as U1db
22import Ubuntu.Components 1.1
23import "../../app/clock"
24
25/*
26 This file is meant to create a fake but fully fleshed clock app with its
27 own database and settings. This will avoid messing with the user data while
28 running the tests.
29*/
30
31MainView {
32 id: clockApp
33
34 // Property to store the state of an application (active or suspended)
35 property bool applicationState: Qt.application.active
36
37 width: units.gu(40)
38 height: units.gu(70)
39 useDeprecatedToolbar: false
40 applicationName: "com.ubuntu.fakeclock.test"
41
42 U1db.Database {
43 id: clockDB
44 path: "user-preferences"
45 }
46
47 U1db.Document {
48 id: clockModeDocument
49 create: true
50 database: clockDB
51 docId: "clockModeDocument"
52 defaults: { "digitalMode": false }
53 }
54
55 DateTime {
56 id: localTimeSource
57 updateInterval: 1000
58 }
59
60 PageStack {
61 id: mainStack
62 objectName: "pageStack"
63
64 Component.onCompleted: push(clockPage)
65
66 ClockPage {
67 id: clockPage
68
69 Loader {
70 id: alarmModelLoader
71 asynchronous: false
72 }
73
74 alarmModel: alarmModelLoader.item
75 bottomEdgeEnabled: alarmModelLoader.status === Loader.Ready
76 clockTime: new Date
77 (
78 localTimeSource.localDateString.split(":")[0],
79 localTimeSource.localDateString.split(":")[1]-1,
80 localTimeSource.localDateString.split(":")[2],
81 localTimeSource.localTimeString.split(":")[0],
82 localTimeSource.localTimeString.split(":")[1],
83 localTimeSource.localTimeString.split(":")[2],
84 localTimeSource.localTimeString.split(":")[3]
85 )
86 }
87 }
88}
089
=== added file 'tests/unit/tst_worldClock.qml'
--- tests/unit/tst_worldClock.qml 1970-01-01 00:00:00 +0000
+++ tests/unit/tst_worldClock.qml 2014-10-14 16:02:15 +0000
@@ -0,0 +1,194 @@
1/*
2 * Copyright (C) 2014 Canonical Ltd
3 *
4 * This file is part of Ubuntu Clock App
5 *
6 * Ubuntu Clock App is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * Ubuntu Clock App is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19import QtQuick 2.0
20import QtTest 1.0
21import Ubuntu.Test 1.0
22import Ubuntu.Components 1.1
23
24MockClockApp {
25 id: clockApp
26
27 ClockTestCase {
28 id: worldClockFeatureTest
29 name: "WorldClockFeatureTest"
30
31 when: windowShown
32
33 property var header
34 property var backButton
35 property var clockPage
36 property var pageStack
37
38 function initTestCase() {
39 header = findChild(clockApp, "MainView_Header")
40 backButton = findChild(header, "customBackButton")
41 pageStack = findChild(clockApp, "pageStack")
42 clockPage = findChild(clockApp, "clockPage")
43 }
44
45 // *********** Helper Functions ************
46
47 function pressAddWorldCityButton() {
48 var addWorldCityButton = findChild(clockApp, "addWorldCityButton")
49 pressButton(addWorldCityButton)
50 }
51
52 function _findWorldCity(cityList, type, cityName, countryName) {
53 /*
54 The list view for the user world city list and the available world
55 city list have the same structure with some minor object name
56 changes. The 'objectPrefix' varible is used to handle that.
57 */
58 var objectPrefix = type === "user" ? "user" : "default"
59
60 for(var i=0; i<cityList.count; i++) {
61 var cityListItem = findChild(clockApp, objectPrefix+"WorldCityItem"+i)
62 var city = findChild(cityListItem, objectPrefix+"CityNameText")
63 var country = findChild(cityListItem, objectPrefix+"CountryNameText")
64
65 if (city.text === cityName && country.text === countryName) {
66 return i
67 }
68 }
69
70 return -1;
71 }
72
73 function findUserWorldCity(cityList, cityName, countryName) {
74 return _findWorldCity(cityList, "user", cityName, countryName)
75 }
76
77 function findDefaultWorldCity(cityList, cityName, countryName) {
78 return _findWorldCity(cityList, "default", cityName, countryName)
79 }
80
81 function assertWorldCityAddition(cityName, countryName) {
82 var cityList = findChild(clockApp, "userWorldCityRepeater")
83
84 // Wait for the user list to be populated with results
85 tryCompareFunction(function() { return cityList.count > 0}, true)
86
87 var cityIndex = findUserWorldCity(cityList, cityName, countryName)
88
89 if (cityIndex === -1) {
90 // If city couldn't be found in the saved city list, fail the test
91 fail("City added during the test cannot be found in the user world city list!")
92 }
93 }
94
95 function deleteWorldCity(cityName, countryName) {
96 var cityList = findChild(clockApp, "userWorldCityRepeater")
97
98 var oldCount = cityList.count
99 var cityIndex = findUserWorldCity(cityList, cityName, countryName)
100
101 if (cityIndex === -1) {
102 fail("City added during the test cannot be found in the user world city list!")
103 }
104 else {
105 var cityListItem = findChild(clockApp, "userWorldCityItem"+cityIndex)
106 swipeToDeleteItem(cityListItem)
107 }
108
109 /*
110 #FIXME: Commented out the following line as deleting a world city
111 when there is only one world city does not decrease the count to 0
112 but leaves it as 1 causing the test to fail. This has been reported
113 in bug #1368393. (Also fails in Autopilot)
114
115 tryCompare(cityList, "count", oldCount-1, 5000, "city list count did not decrease")
116
117 The wait() call below is to ensure that the world city is deleted properly
118 which wouldn't be required if could do the count decrease check mentioned above.
119 */
120
121 wait(1000)
122 }
123
124 function addCityFromList(cityName, countryName) {
125 var worldCityPage = getPage(pageStack, "worldCityList")
126 var cityList = findChild(worldCityPage, "cityList")
127
128 // Wait for the list to be populated with results
129 tryCompareFunction(function() { return cityList.count > 0}, true)
130
131 var cityIndex = findDefaultWorldCity(cityList, cityName, countryName)
132
133 if (cityIndex === -1) {
134 fail("City cannot be found in the local world city list")
135 }
136
137 var cityListItem = findChild(cityList, "defaultWorldCityItem"+cityIndex)
138 mouseClick(cityListItem, centerOf(cityListItem).x, centerOf(cityListItem).y)
139 }
140
141 function addCityBySearchingOnline(cityName, countryName) {
142 pressHeaderButton(header, "searchButton")
143 var searchField = findChild(clockApp, "searchField")
144 tryCompare(searchField, "visible", true, 5000, "Search field is not visible")
145 typeString(cityName)
146 addCityFromList(cityName, countryName)
147 }
148
149 // *********** Test Functions *************
150
151 /*
152 Test to check if a city found in the world city list can be added
153 to the user world city list.
154 */
155 function test_addCityAlreadyPresentInWorldCityList() {
156 var clockPage = getPage(pageStack, "clockPage")
157
158 pressAddWorldCityButton()
159
160 var worldCityPage = getPage(pageStack, "worldCityList")
161 waitForRendering(worldCityPage)
162
163 addCityFromList("Amsterdam", "Netherlands")
164 assertWorldCityAddition("Amsterdam", "Netherlands")
165
166 // Clean up after the test by deleting the city which was added during the test
167 deleteWorldCity("Amsterdam", "Netherlands")
168 }
169
170 /*
171 Test to check if a city now found in the world city list can be added
172 by searcing it online and then adding it from the results returned.
173 */
174 function test_addCityBySearchingOnline() {
175 var clockPage = getPage(pageStack, "clockPage")
176
177 pressAddWorldCityButton()
178
179 var worldCityPage = getPage(pageStack, "worldCityList")
180 waitForRendering(worldCityPage)
181
182 /*
183 #TODO: Jenkins machine may run in a confined environment with no
184 access to internet to run this function. Ideally we should mock
185 the data given to this function.
186 */
187 addCityBySearchingOnline("Venice", "Provincia di Venezia, Veneto, Italy")
188 assertWorldCityAddition("Venice", " Veneto, Italy")
189
190 // Clean up after the test by deleting the city which was added during the test
191 deleteWorldCity("Venice", " Veneto, Italy")
192 }
193 }
194}

Subscribers

People subscribed via source and target branches