Merge lp:~ahayzen/ubuntu-weather-app/reboot-1452497-add-location-from-home into lp:ubuntu-weather-app

Proposed by Andrew Hayzen
Status: Merged
Approved by: Victor Thompson
Approved revision: 82
Merged at revision: 80
Proposed branch: lp:~ahayzen/ubuntu-weather-app/reboot-1452497-add-location-from-home
Merge into: lp:ubuntu-weather-app
Diff against target: 416 lines (+196/-30)
7 files modified
app/ui/AddLocationPage.qml (+22/-7)
app/ui/LocationsPage.qml (+3/-0)
debian/changelog (+3/-0)
po/com.ubuntu.weather.pot (+10/-10)
tests/autopilot/ubuntu_weather_app/__init__.py (+53/-12)
tests/autopilot/ubuntu_weather_app/tests/test_add_location_page.py (+100/-0)
tests/autopilot/ubuntu_weather_app/tests/test_empty_state.py (+5/-1)
To merge this branch: bzr merge lp:~ahayzen/ubuntu-weather-app/reboot-1452497-add-location-from-home
Reviewer Review Type Date Requested Status
Victor Thompson Approve
Ubuntu Phone Apps Jenkins Bot continuous-integration Approve
Andrew Hayzen Abstain
Review via email: mp+266051@code.launchpad.net

Commit message

* Create autopilot test which adds a location via searching
* Create autopilot test which adds a location via cached results
* Fix for racy search bar causing incorrect search query when typed quickly

Description of the change

* Create autopilot test which adds a location via searching
* Create autopilot test which adds a location via cached results
* Fix for racy search bar causing incorrect search query when typed quickly

These test that you can add a location from the add locations page by either searching for a location or using the cached list.

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
Victor Thompson (vthompson) wrote :

I have some inline comments that should be addressed. Also, of the 5 or so runs I did, one instance incorrectly resized the window rather than grabbing the tool tip. I'm not 100% this was or was not my fault, but we don't want this to be a "flaky" test...

review: Needs Fixing
Revision history for this message
Andrew Hayzen (ahayzen) wrote :

If in [0] we change to only having the bottom edge as an entry point for adding locations, then this and the other test should be moved into their own test_locations_page file and class.

0 - https://code.launchpad.net/~ahayzen/ubuntu-weather-app/reboot-fix-no-settings-button-empty-state/+merge/266044

73. By Andrew Hayzen

* Merge of trunk and test from lp:~ahayzen/ubuntu-weather-app/reboot-1452497-add-location-from-empty-state
* Move tests into test_add_location_page.py

74. By Andrew Hayzen

* Check that the location name of the added item is correct

75. By Andrew Hayzen

* Remove old test code

76. By Andrew Hayzen

* Remove unneeded comments

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

* Update changelog to reference bug #

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
Victor Thompson (vthompson) wrote :

I thought you said this was rebased on top of your empty state fix? There are currently AP and changelog merge conflicts you'll need to resolve.

Also, I've had the search test occasionally fail for me. I think you'll want to add a delay after entering the search term or maybe have a wait for the location name to be item 0 before clicking?

review: Needs Fixing
Revision history for this message
Victor Thompson (vthompson) wrote :

One more thing, I should have had you remove "ubuntu_weather_app.tests.test_empty_state.TestEmptyState.test_add_location_button" in that last MP. Can you remove it in this mp?

78. By Andrew Hayzen

* Merge of trunk

79. By Andrew Hayzen

* Fix for double merge conflicts

Revision history for this message
Andrew Hayzen (ahayzen) wrote :

Still need to add the delay to the search, otherwise it should be good now, so failing myself until I've done that.

review: Needs Fixing
80. By Andrew Hayzen

* Add delay to search

Revision history for this message
Andrew Hayzen (ahayzen) wrote :

Added a delay of 250ms to the search, not sure if there a standard value for this? Let me know if you want it shorter/longer, 250ms feels around right to me.

review: Abstain
Revision history for this message
Victor Thompson (vthompson) wrote :

On my first 3 runs the search test failed:

Traceback (most recent call last):
  File "/home/victor/Development/reboot-1452497-add-location-from-home/tests/autopilot/ubuntu_weather_app/tests/test_add_location_page.py", line 84, in test_add_location_via_search
    self.assertThat(self.locations_page.visible, Eventually(Equals(True)))
  File "/usr/lib/python3/dist-packages/testtools/testcase.py", line 423, in assertThat
    raise mismatch_error
testtools.matchers._impl.MismatchError: After 10.0 seconds test on LocationsPage.visible failed: True != dbus.Boolean(False, variant_level=1)

I didn't think you'd want to add a timer to the app to get a delay--I assumed you'd add a delay to the test.

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

* Fix for search so that autopilot waits for it to complete

82. By Andrew Hayzen

* Include search fix in changelog

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
Victor Thompson (vthompson) wrote :

This lgtm. I'm still not sure the timer solution is the proper one for the "racy" search issue. I can still force the search to not populate things the way I'd assume if I type, stop typing, and start typing again. Let's see if it becomes problematic.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'app/ui/AddLocationPage.qml'
--- app/ui/AddLocationPage.qml 2015-06-28 23:37:10 +0000
+++ app/ui/AddLocationPage.qml 2015-08-06 00:13:15 +0000
@@ -35,6 +35,8 @@
35 */35 */
36 flickable: null36 flickable: null
3737
38 property bool searching: citiesModel.loading || searchTimer.running
39
38 state: "default"40 state: "default"
39 states: [41 states: [
40 PageHeadState {42 PageHeadState {
@@ -48,6 +50,7 @@
48 actions: [50 actions: [
49 Action {51 Action {
50 iconName: "search"52 iconName: "search"
53 objectName: "search"
51 text: i18n.tr("City")54 text: i18n.tr("City")
52 onTriggered: {55 onTriggered: {
53 addLocationPage.state = "search"56 addLocationPage.state = "search"
@@ -83,6 +86,23 @@
83 }86 }
84 ]87 ]
8588
89 // Outside component so property can bind to for autopilot
90 Timer {
91 id: searchTimer
92 interval: 250
93 onTriggered: {
94 if (searchComponentLoader.item) { // check component exists
95 if (searchComponentLoader.item.text.trim() === "") {
96 loadEmpty()
97 } else {
98 loadFromProvider(searchComponentLoader.item.text)
99 }
100 } else {
101 loadEmpty()
102 }
103 }
104 }
105
86 Component {106 Component {
87 id: searchComponent107 id: searchComponent
88 TextField {108 TextField {
@@ -93,13 +113,7 @@
93 placeholderText: i18n.tr("Search city")113 placeholderText: i18n.tr("Search city")
94 hasClearButton: true114 hasClearButton: true
95115
96 onTextChanged: {116 onTextChanged: searchTimer.restart()
97 if (text.trim() === "") {
98 loadEmpty()
99 } else {
100 loadFromProvider(text)
101 }
102 }
103 }117 }
104 }118 }
105119
@@ -206,6 +220,7 @@
206220
207 delegate: ListItem {221 delegate: ListItem {
208 divider.visible: false222 divider.visible: false
223 objectName: "addLocation" + index
209 Column {224 Column {
210 anchors {225 anchors {
211 left: parent.left226 left: parent.left
212227
=== modified file 'app/ui/LocationsPage.qml'
--- app/ui/LocationsPage.qml 2015-07-29 21:34:07 +0000
+++ app/ui/LocationsPage.qml 2015-08-06 00:13:15 +0000
@@ -38,6 +38,7 @@
38 actions: [38 actions: [
39 Action {39 Action {
40 iconName: "add"40 iconName: "add"
41 objectName: "addLocation"
41 onTriggered: mainPageStack.push(Qt.resolvedUrl("AddLocationPage.qml"))42 onTriggered: mainPageStack.push(Qt.resolvedUrl("AddLocationPage.qml"))
42 }43 }
43 ]44 ]
@@ -153,6 +154,7 @@
153154
154 delegate: WeatherListItem {155 delegate: WeatherListItem {
155 id: locationsListItem156 id: locationsListItem
157 objectName: "location" + index
156 leftSideAction: Remove {158 leftSideAction: Remove {
157 onTriggered: storage.removeLocation(index)159 onTriggered: storage.removeLocation(index)
158 }160 }
@@ -194,6 +196,7 @@
194196
195 Label {197 Label {
196 id: locationName198 id: locationName
199 objectName: "name"
197 elide: Text.ElideRight200 elide: Text.ElideRight
198 fontSize: "medium"201 fontSize: "medium"
199 text: name202 text: name
200203
=== modified file 'debian/changelog'
--- debian/changelog 2015-07-30 02:55:02 +0000
+++ debian/changelog 2015-08-06 00:13:15 +0000
@@ -19,6 +19,9 @@
19 * Remove add location button19 * Remove add location button
20 * Change phrasing of manual add location20 * Change phrasing of manual add location
21 * Conditionally show "searching for current location" depending on the detectCurrentLocation setting21 * Conditionally show "searching for current location" depending on the detectCurrentLocation setting
22 * Create autopilot test which adds a location via searching (LP: #1452497)
23 * Create autopilot test which adds a location via cached results (LP: #1452497)
24 * Fix for racy search bar causing incorrect search query when typed quickly
2225
23 -- Victor Thompson <victor.thompson@gmail.com> Mon, 01 Jun 2015 20:11:23 -050026 -- Victor Thompson <victor.thompson@gmail.com> Mon, 01 Jun 2015 20:11:23 -0500
2427
2528
=== modified file 'po/com.ubuntu.weather.pot'
--- po/com.ubuntu.weather.pot 2015-07-29 20:34:57 +0000
+++ po/com.ubuntu.weather.pot 2015-08-06 00:13:15 +0000
@@ -8,7 +8,7 @@
8msgstr ""8msgstr ""
9"Project-Id-Version: ubuntu-weather-app\n"9"Project-Id-Version: ubuntu-weather-app\n"
10"Report-Msgid-Bugs-To: \n"10"Report-Msgid-Bugs-To: \n"
11"POT-Creation-Date: 2015-07-29 21:25+0100\n"11"POT-Creation-Date: 2015-08-06 01:02+0100\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"14"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -82,39 +82,39 @@
82msgid "Select a city"82msgid "Select a city"
83msgstr ""83msgstr ""
8484
85#: ../app/ui/AddLocationPage.qml:45 ../app/ui/AddLocationPage.qml:6685#: ../app/ui/AddLocationPage.qml:47 ../app/ui/AddLocationPage.qml:69
86msgid "Back"86msgid "Back"
87msgstr ""87msgstr ""
8888
89#: ../app/ui/AddLocationPage.qml:5189#: ../app/ui/AddLocationPage.qml:54
90msgid "City"90msgid "City"
91msgstr ""91msgstr ""
9292
93#: ../app/ui/AddLocationPage.qml:9393#: ../app/ui/AddLocationPage.qml:113
94msgid "Search city"94msgid "Search city"
95msgstr ""95msgstr ""
9696
97#: ../app/ui/AddLocationPage.qml:27897#: ../app/ui/AddLocationPage.qml:293
98msgid "No city found"98msgid "No city found"
99msgstr ""99msgstr ""
100100
101#: ../app/ui/AddLocationPage.qml:291101#: ../app/ui/AddLocationPage.qml:306
102msgid "Couldn't load weather data, please try later again!"102msgid "Couldn't load weather data, please try later again!"
103msgstr ""103msgstr ""
104104
105#: ../app/ui/AddLocationPage.qml:301105#: ../app/ui/AddLocationPage.qml:316
106msgid "Location already added."106msgid "Location already added."
107msgstr ""107msgstr ""
108108
109#: ../app/ui/AddLocationPage.qml:304109#: ../app/ui/AddLocationPage.qml:319
110msgid "OK"110msgid "OK"
111msgstr ""111msgstr ""
112112
113#: ../app/ui/HomePage.qml:31 ../app/ui/LocationsPage.qml:30113#: ../app/ui/HomePage.qml:31 ../app/ui/LocationsPage.qml:31
114msgid "Locations"114msgid "Locations"
115msgstr ""115msgstr ""
116116
117#: ../app/ui/LocationsPage.qml:104117#: ../app/ui/LocationsPage.qml:106
118msgid "Current Location"118msgid "Current Location"
119msgstr ""119msgstr ""
120120
121121
=== modified file 'tests/autopilot/ubuntu_weather_app/__init__.py'
--- tests/autopilot/ubuntu_weather_app/__init__.py 2015-07-29 21:34:07 +0000
+++ tests/autopilot/ubuntu_weather_app/__init__.py 2015-08-06 00:13:15 +0000
@@ -10,7 +10,6 @@
10import logging10import logging
11from ubuntuuitoolkit import MainView, UbuntuUIToolkitCustomProxyObjectBase11from ubuntuuitoolkit import MainView, UbuntuUIToolkitCustomProxyObjectBase
1212
13
14logger = logging.getLogger(__name__)13logger = logging.getLogger(__name__)
1514
1615
@@ -51,18 +50,27 @@
5150
52class Page(UbuntuUIToolkitCustomProxyObjectBase):51class Page(UbuntuUIToolkitCustomProxyObjectBase):
53 """Autopilot helper for Pages."""52 """Autopilot helper for Pages."""
54 def __init__(self, *args):53 def __init__(self, *args, **kwargs):
55 super(Page, self).__init__(*args)54 super(Page, self).__init__(*args, **kwargs)
55
56 # Use only objectName due to bug 1350532 as it is MainView12
57 self.main_view = self.get_root_instance().select_single(
58 objectName="weather")
59
60 def click_back(self):
61 return self.main_view.get_header().click_back_button()
5662
5763
58class PageWithBottomEdge(Page):64class PageWithBottomEdge(Page):
59 """Autopilot helper for PageWithBottomEdge."""65 """
60 def __init__(self, *args):66 An emulator class that makes it easy to interact with the bottom edge
61 super(PageWithBottomEdge, self).__init__(*args)67 swipe page
68 """
69 def __init__(self, *args, **kwargs):
70 super(PageWithBottomEdge, self).__init__(*args, **kwargs)
6271
63 def reveal_bottom_edge_page(self):72 def reveal_bottom_edge_page(self):
64 """Bring the bottom edge page to the screen"""73 """Bring the bottom edge page to the screen"""
65
66 self.bottomEdgePageLoaded.wait_for(True)74 self.bottomEdgePageLoaded.wait_for(True)
6775
68 try:76 try:
@@ -73,7 +81,6 @@
73 start_y = (action_item.globalRect.y +81 start_y = (action_item.globalRect.y +
74 (action_item.height * 0.5))82 (action_item.height * 0.5))
75 stop_y = start_y - (self.height * 0.7)83 stop_y = start_y - (self.height * 0.7)
76
77 self.pointing_device.drag(start_x, start_y,84 self.pointing_device.drag(start_x, start_y,
78 start_x, stop_y, rate=2)85 start_x, stop_y, rate=2)
79 self.isReady.wait_for(True)86 self.isReady.wait_for(True)
@@ -84,14 +91,36 @@
8491
85class AddLocationPage(Page):92class AddLocationPage(Page):
86 """Autopilot helper for AddLocationPage."""93 """Autopilot helper for AddLocationPage."""
87 def __init__(self, *args):94 def __init__(self, *args, **kwargs):
88 super(AddLocationPage, self).__init__(*args)95 super(AddLocationPage, self).__init__(*args, **kwargs)
96
97 @click_object
98 def click_location(self, index):
99 return self.select_single("UCListItem",
100 objectName="addLocation" + str(index))
101
102 def click_search_action(self):
103 self.main_view.get_header().click_action_button("search")
104
105 def get_search_field(self):
106 header = self.main_view.get_header()
107
108 return header.select_single("TextField", objectName="searchField")
109
110 def search(self, value):
111 self.click_search_action()
112
113 search_field = self.get_search_field()
114 search_field.write(value)
115
116 # Wait for model to finish loading
117 self.searching.wait_for(False)
89118
90119
91class HomePage(PageWithBottomEdge):120class HomePage(PageWithBottomEdge):
92 """Autopilot helper for HomePage."""121 """Autopilot helper for HomePage."""
93 def __init__(self, *args):122 def __init__(self, *args, **kwargs):
94 super(HomePage, self).__init__(*args)123 super(HomePage, self).__init__(*args, **kwargs)
95124
96 def get_location_count(self):125 def get_location_count(self):
97 return self.wait_select_single(126 return self.wait_select_single(
@@ -103,6 +132,13 @@
103 def __init__(self, *args, **kwargs):132 def __init__(self, *args, **kwargs):
104 super(LocationsPage, self).__init__(*args, **kwargs)133 super(LocationsPage, self).__init__(*args, **kwargs)
105134
135 def click_add_location_action(self):
136 self.main_view.get_header().click_action_button("addLocation")
137
138 def get_location(self, index):
139 return self.select_single(WeatherListItem,
140 objectName="location" + str(index))
141
106142
107class MainView(MainView):143class MainView(MainView):
108 """Autopilot custom proxy object for the MainView."""144 """Autopilot custom proxy object for the MainView."""
@@ -111,3 +147,8 @@
111 def __init__(self, *args):147 def __init__(self, *args):
112 super(MainView, self).__init__(*args)148 super(MainView, self).__init__(*args)
113 self.visible.wait_for(True)149 self.visible.wait_for(True)
150
151
152class WeatherListItem(UbuntuUIToolkitCustomProxyObjectBase):
153 def get_name(self):
154 return self.select_single("Label", objectName="name").text
114155
=== added file 'tests/autopilot/ubuntu_weather_app/tests/test_add_location_page.py'
--- tests/autopilot/ubuntu_weather_app/tests/test_add_location_page.py 1970-01-01 00:00:00 +0000
+++ tests/autopilot/ubuntu_weather_app/tests/test_add_location_page.py 2015-08-06 00:13:15 +0000
@@ -0,0 +1,100 @@
1# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2# Copyright 2013, 2014, 2015 Canonical
3#
4# This program is free software: you can redistribute it and/or modify it
5# under the terms of the GNU General Public License version 3, as published
6# by the Free Software Foundation.
7
8"""Ubuntu Weather app autopilot tests."""
9
10from __future__ import absolute_import
11
12import logging
13from autopilot.matchers import Eventually
14from testtools.matchers import Equals
15
16
17from ubuntu_weather_app.tests import UbuntuWeatherAppTestCaseWithData
18
19logger = logging.getLogger(__name__)
20
21
22class TestAddLocationPage(UbuntuWeatherAppTestCaseWithData):
23
24 """ Tests for the add locations page
25 setUp jumps to add to locations page as all tests start from here """
26
27 def setUp(self):
28 super(TestAddLocationPage, self).setUp()
29
30 # Get the start count of the homepage
31 self.home_page = self.app.get_home_page()
32 self.start_count = self.home_page.get_location_count()
33
34 # Open the locations page from bottom edge
35 self.home_page.reveal_bottom_edge_page()
36
37 self.locations_page = self.app.get_locations_page()
38 self.locations_page.visible.wait_for(True)
39
40 # Select the add header action and get the add locations page
41 self.locations_page.click_add_location_action()
42
43 # Get the add locations page
44 self.add_location_page = self.app.get_add_location_page()
45 self.add_location_page.visible.wait_for(True)
46
47 def test_add_location_via_cache(self):
48 """ tests adding a location via cached location list """
49
50 # Select the location
51 self.add_location_page.click_location(0)
52
53 # Check locations page is now visible
54 self.assertThat(self.locations_page.visible, Eventually(Equals(True)))
55
56 # Get the list item of the added location
57 list_item = self.locations_page.get_location(self.start_count)
58
59 # Check that the name is correct
60 self.assertThat(list_item.get_name(), Equals("Amsterdam"))
61
62 # Go back to the homepage
63 self.locations_page.click_back()
64
65 # Check homepage is now visible
66 self.assertThat(self.home_page.visible, Eventually(Equals(True)))
67
68 # Check that the location was added
69 self.assertThat(self.home_page.get_location_count,
70 Eventually(Equals(self.start_count + 1)))
71
72 def test_add_location_via_search(self):
73 """ tests adding a location via searching for the location """
74
75 location_name = "Paris"
76
77 # Perform search
78 self.add_location_page.search(location_name)
79
80 # Select the location
81 self.add_location_page.click_location(0)
82
83 # Check locations page is now visible
84 self.assertThat(self.locations_page.visible, Eventually(Equals(True)))
85
86 # Get the list item of the added location
87 list_item = self.locations_page.get_location(self.start_count)
88
89 # Check that the name is correct
90 self.assertThat(list_item.get_name(), Equals(location_name))
91
92 # Go back to the homepage
93 self.locations_page.click_back()
94
95 # Check homepage is now visible
96 self.assertThat(self.home_page.visible, Eventually(Equals(True)))
97
98 # Check that the location was added
99 self.assertThat(self.home_page.get_location_count,
100 Eventually(Equals(self.start_count + 1)))
0101
=== modified file 'tests/autopilot/ubuntu_weather_app/tests/test_empty_state.py'
--- tests/autopilot/ubuntu_weather_app/tests/test_empty_state.py 2015-07-29 21:34:07 +0000
+++ tests/autopilot/ubuntu_weather_app/tests/test_empty_state.py 2015-08-06 00:13:15 +0000
@@ -24,12 +24,16 @@
24 def setUp(self):24 def setUp(self):
25 super(TestEmptyState, self).setUp()25 super(TestEmptyState, self).setUp()
2626
27 def test_add_location_button(self):27 def test_add_locations_page_from_bottom_edge(self):
28 """ tests that the add location page is shown after swiping up28 """ tests that the add location page is shown after swiping up
29 the bottom edge"""29 the bottom edge"""
3030
31 home_page = self.app.get_home_page()31 home_page = self.app.get_home_page()
32 home_page.visible.wait_for(True)32 home_page.visible.wait_for(True)
33
34 # Check that there are no locations
35 self.assertThat(home_page.get_location_count, Eventually(Equals(0)))
36
33 home_page.reveal_bottom_edge_page()37 home_page.reveal_bottom_edge_page()
3438
35 locations_page = self.app.get_locations_page()39 locations_page = self.app.get_locations_page()

Subscribers

People subscribed via source and target branches

to all changes: