Merge lp:~elopio/ubuntu-ui-toolkit/listview-scroll_to_bottom into lp:ubuntu-ui-toolkit

Proposed by Leo Arias
Status: Merged
Approved by: Cris Dywan
Approved revision: 928
Merged at revision: 957
Proposed branch: lp:~elopio/ubuntu-ui-toolkit/listview-scroll_to_bottom
Merge into: lp:ubuntu-ui-toolkit
Diff against target: 254 lines (+98/-84)
2 files modified
tests/autopilot/ubuntuuitoolkit/emulators.py (+73/-31)
tests/autopilot/ubuntuuitoolkit/tests/test_emulators.py (+25/-53)
To merge this branch: bzr merge lp:~elopio/ubuntu-ui-toolkit/listview-scroll_to_bottom
Reviewer Review Type Date Requested Status
Florian Boucault (community) Approve
Cris Dywan Approve
PS Jenkins bot continuous-integration Approve
Javier Collado Pending
Richard Huddie Pending
VĂ­ctor R. Ruiz Pending
Review via email: mp+202129@code.launchpad.net

Commit message

On the autopilot listview emulator, scroll to the bottom to try to find elements not yet created.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Leo Arias (elopio) wrote :

We can't just scroll to the bottom, because then the items on the top will not exists.
On this version, we are scrolling one 'page' at a time.

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: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Javier Collado (javier.collado) wrote :

The code looks good, but still I'm not familiar enough with it, so I have a
couple of questions:

- My understanding is that the statements in test_emulators.py in "delegate"
  (line 193 in the MP) create the elements that were previously created
  manually. Is that correct? How come that there isn't any loop counter or
  anything? Does using just one number as in "%1" mean that only the elements
  from 0 to 9 will be created?

- The _is_element_clickable method seems to make sense, but it doesn't consider
  the x coordinate. If the element is wide enough I guess it might happen that
  its center in the y axis is visible, but not the center in the x axis. Maybe
  there's some assumption or precondition that I'm missing?

Revision history for this message
Leo Arias (elopio) wrote :

Thanks for reviewing Javier.
The changes on the delegate are pretty nice. I didn't know how to do that, but kalikiana gave me the code. You can do a loop by just using:
191 + model: 20
So elements from 0 to 19 are created.

About _is_element_clickable, you are right. I'm currently not taking care of horizontal scrolling. With vertical scrolling we solve most of the cases for current apps, but we'll need to add the other one soon. I'll make a comment and add a bug to implement it in a following branch.

For now, going back to work in progress as the drag in the phone is still to fast and is taking us further than we need. I have solved the slow drag in https://code.launchpad.net/~elopio/autopilot/fix1257055-slow_drag/+merge/202205 just waiting for thomi.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
928. By Leo Arias

Fixed pyflakes.

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

Nice stuff!

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

FAIL: ubuntu_rssreader_app.tests.test_rssreader.TestMainWindow.test_add_remove_feed_and_topic(with touch)
http://paste.ubuntu.com/6994140/

Revision history for this message
Florian Boucault (fboucault) wrote :

> FAIL: ubuntu_rssreader_app.tests.test_rssreader.TestMainWindow.test_add_remove
> _feed_and_topic(with touch)
> http://paste.ubuntu.com/6994140/

After rerunning tests ubuntu_rssreader_app, everything passes:

CI@home OK http://paste.ubuntu.com/6994140/ + rerun http://paste.ubuntu.com/6994912/

review: Approve
Revision history for this message
Leo Arias (elopio) wrote :

I'm improving this test_add_remove_feed_and_topic. It's ugly now, so you can expect to get random issues. Next week it will be pretty.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'tests/autopilot/ubuntuuitoolkit/emulators.py'
2--- tests/autopilot/ubuntuuitoolkit/emulators.py 2014-01-30 15:26:21 +0000
3+++ tests/autopilot/ubuntuuitoolkit/emulators.py 2014-02-22 00:04:26 +0000
4@@ -15,7 +15,6 @@
5 # along with this program. If not, see <http://www.gnu.org/licenses/>.
6
7 import logging
8-import time
9 from distutils import version
10
11 import autopilot
12@@ -527,7 +526,7 @@
13 def click_element(self, objectName):
14 """Click an element from the list.
15
16- It swipes the element into view if it's not fully visible.
17+ It swipes the element into view if it's center is not visible.
18
19 :parameter objectName: The objectName property of the element to click.
20
21@@ -537,38 +536,81 @@
22 self.pointing_device.click_object(element)
23
24 def _swipe_element_into_view(self, objectName):
25- element = self.select_single(objectName=objectName)
26- x, y, width, height = self.globalRect
27- start_x = x + (width / 2)
28- start_y = y + (height / 2)
29+ element = self._select_element(objectName)
30
31- while not self._is_element_fully_visible(objectName):
32- stop_x = start_x
33+ while not self._is_element_clickable(objectName):
34 if element.globalRect.y < self.globalRect.y:
35- stop_y = start_y + element.implicitHeight
36- else:
37- stop_y = start_y - element.implicitHeight
38-
39- if platform.model() == 'Desktop':
40- # The drag on the desktop is done two fast, so we are left at
41- # the bottom or at the top of the list, sometimes missing the
42- # element we are looking for.
43- # TODO: use the slow drag once it's implemented:
44- # https://bugs.launchpad.net/autopilot/+bug/1257055
45- # --elopio - 2014-01-09
46- self.pointing_device.move(start_x, start_y)
47- self.pointing_device.press()
48- self.pointing_device.move(stop_x, stop_y)
49- time.sleep(0.3)
50- self.pointing_device.release()
51- else:
52- self.pointing_device.drag(start_x, start_y, stop_x, stop_y)
53-
54- def _is_element_fully_visible(self, objectName):
55+ self._show_more_elements_above()
56+ else:
57+ self._show_more_elements_below()
58+
59+ def _select_element(self, object_name):
60+ try:
61+ return self.select_single(objectName=object_name)
62+ except dbus.StateNotFoundError:
63+ # If the list is big, elements will only be created when we scroll
64+ # them into view.
65+ self._scroll_to_top()
66+ while not self.atYEnd:
67+ self._show_more_elements_below()
68+ try:
69+ return self.select_single(objectName=object_name)
70+ except dbus.StateNotFoundError:
71+ pass
72+ raise ToolkitEmulatorException(
73+ 'List element with objectName "{}" not found.'.format(
74+ object_name))
75+
76+ @autopilot_logging.log_action(logger.info)
77+ def _scroll_to_top(self):
78+ x, y, width, height = self.globalRect
79+ while not self.atYBeginning:
80+ self._show_more_elements_above()
81+
82+ @autopilot_logging.log_action(logger.info)
83+ def _show_more_elements_below(self):
84+ if self.atYEnd:
85+ raise ToolkitEmulatorException('There are no more elements below.')
86+ else:
87+ self._show_more_elements('below')
88+
89+ @autopilot_logging.log_action(logger.info)
90+ def _show_more_elements_above(self):
91+ if self.atYBeginning:
92+ raise ToolkitEmulatorException('There are no more elements above.')
93+ else:
94+ self._show_more_elements('above')
95+
96+ def _show_more_elements(self, direction):
97+ x, y, width, height = self.globalRect
98+ start_x = stop_x = x + (width / 2)
99+ # Start and stop just a little under the top of the list.
100+ top = y + 5
101+ bottom = y + height - 5
102+ if direction == 'below':
103+ start_y = bottom
104+ stop_y = top
105+ elif direction == 'above':
106+ start_y = top
107+ stop_y = bottom
108+ else:
109+ raise ToolkitEmulatorException(
110+ 'Invalid direction {}.'.format(direction))
111+ self._slow_drag(start_x, stop_x, start_y, stop_y)
112+ self.dragging.wait_for(False)
113+ self.moving.wait_for(False)
114+
115+ def _slow_drag(self, start_x, stop_x, start_y, stop_y):
116+ # If we drag too fast, we end up scrolling more than what we
117+ # should, sometimes missing the element we are looking for.
118+ self.pointing_device.drag(start_x, start_y, stop_x, stop_y, rate=5)
119+
120+ def _is_element_clickable(self, objectName):
121+ """Return True if the center of the element is visible."""
122 element = self.select_single(objectName=objectName)
123- return (element.globalRect.y >= self.globalRect.y and
124- element.globalRect.y + element.globalRect.height <=
125- self.globalRect.y + self.globalRect.height)
126+ element_center = element.globalRect.y + element.globalRect.height / 2
127+ return (element_center >= self.globalRect.y and
128+ element_center <= self.globalRect.y + self.globalRect.height)
129
130
131 class Empty(UbuntuUIToolkitEmulatorBase):
132
133=== modified file 'tests/autopilot/ubuntuuitoolkit/tests/test_emulators.py'
134--- tests/autopilot/ubuntuuitoolkit/tests/test_emulators.py 2014-01-13 15:23:25 +0000
135+++ tests/autopilot/ubuntuuitoolkit/tests/test_emulators.py 2014-02-22 00:04:26 +0000
136@@ -574,47 +574,6 @@
137 text: "No element clicked."
138 }
139
140- ListModel {
141- id: testModel
142-
143- ListElement {
144- objectName: "testListElement1"
145- label: "test list element 1"
146- }
147- ListElement {
148- objectName: "testListElement2"
149- label: "test list element 2"
150- }
151- ListElement {
152- objectName: "testListElement3"
153- label: "test list element 3"
154- }
155- ListElement {
156- objectName: "testListElement4"
157- label: "test list element 4"
158- }
159- ListElement {
160- objectName: "testListElement5"
161- label: "test list element 5"
162- }
163- ListElement {
164- objectName: "testListElement6"
165- label: "test list element 6"
166- }
167- ListElement {
168- objectName: "testListElement7"
169- label: "test list element 7"
170- }
171- ListElement {
172- objectName: "testListElement8"
173- label: "test list element 8"
174- }
175- ListElement {
176- objectName: "testListElement9"
177- label: "test list element 9"
178- }
179- }
180-
181 ListView {
182 id: testListView
183 objectName: "testListView"
184@@ -622,13 +581,13 @@
185 anchors.right: parent.right
186 height: column.height - clickedLabel.paintedHeight
187 clip: true
188- model: testModel
189+ model: 20
190
191 delegate: ListItem.Standard {
192- text: model.label
193- objectName: model.objectName
194- onClicked: clickedLabel.text = model.objectName
195- height: units.gu(5)
196+ objectName: "testListElement%1".arg(index)
197+ text: "test list element %1".arg(index)
198+ onClicked: clickedLabel.text = objectName
199+ height: units.gu(5)
200 }
201 }
202 }
203@@ -648,32 +607,45 @@
204 self.assertIsInstance(self.list_view, emulators.QQuickListView)
205
206 def test_click_element(self):
207- self.list_view.click_element('testListElement1')
208- self.assertEqual(self.label.text, 'testListElement1')
209+ self.list_view.click_element('testListElement0')
210+ self.assertEqual(self.label.text, 'testListElement0')
211
212 def test_click_element_outside_view_below(self):
213 # Click the first element out of view to make sure we are not scrolling
214 # to the bottom at once.
215 self.assertFalse(
216- self.list_view._is_element_fully_visible('testListElement5'))
217+ self.list_view._is_element_clickable('testListElement5'))
218
219 self.list_view.click_element('testListElement5')
220 self.assertEqual(self.label.text, 'testListElement5')
221
222 def test_click_element_outside_view_above(self):
223- # First we need to scroll to the 8th element in order for the 9th to be
224- # created.
225- self.list_view.click_element('testListElement8')
226 self.list_view.click_element('testListElement9')
227
228 # Click the first element out of view to make sure we are not scrolling
229 # to the top at once.
230 self.assertFalse(
231- self.list_view._is_element_fully_visible('testListElement4'))
232+ self.list_view._is_element_clickable('testListElement4'))
233
234 self.list_view.click_element('testListElement4')
235 self.assertEqual(self.label.text, 'testListElement4')
236
237+ def test_click_element_not_created_at_start(self):
238+ objectName = 'testListElement19'
239+ self.assertRaises(
240+ dbus.StateNotFoundError,
241+ self.list_view.select_single,
242+ objectName=objectName)
243+ self.list_view.click_element(objectName)
244+
245+ def test_click_unexisting_element(self):
246+ error = self.assertRaises(
247+ emulators.ToolkitEmulatorException,
248+ self.list_view.click_element,
249+ 'unexisting')
250+ self.assertEqual(
251+ str(error), 'List element with objectName "unexisting" not found.')
252+
253
254 class SwipeToDeleteTestCase(tests.QMLStringAppTestCase):
255

Subscribers

People subscribed via source and target branches

to status/vote changes: