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
=== modified file 'tests/autopilot/ubuntuuitoolkit/emulators.py'
--- tests/autopilot/ubuntuuitoolkit/emulators.py 2014-01-30 15:26:21 +0000
+++ tests/autopilot/ubuntuuitoolkit/emulators.py 2014-02-22 00:04:26 +0000
@@ -15,7 +15,6 @@
15# along with this program. If not, see <http://www.gnu.org/licenses/>.15# along with this program. If not, see <http://www.gnu.org/licenses/>.
1616
17import logging17import logging
18import time
19from distutils import version18from distutils import version
2019
21import autopilot20import autopilot
@@ -527,7 +526,7 @@
527 def click_element(self, objectName):526 def click_element(self, objectName):
528 """Click an element from the list.527 """Click an element from the list.
529528
530 It swipes the element into view if it's not fully visible.529 It swipes the element into view if it's center is not visible.
531530
532 :parameter objectName: The objectName property of the element to click.531 :parameter objectName: The objectName property of the element to click.
533532
@@ -537,38 +536,81 @@
537 self.pointing_device.click_object(element)536 self.pointing_device.click_object(element)
538537
539 def _swipe_element_into_view(self, objectName):538 def _swipe_element_into_view(self, objectName):
540 element = self.select_single(objectName=objectName)539 element = self._select_element(objectName)
541 x, y, width, height = self.globalRect
542 start_x = x + (width / 2)
543 start_y = y + (height / 2)
544540
545 while not self._is_element_fully_visible(objectName):541 while not self._is_element_clickable(objectName):
546 stop_x = start_x
547 if element.globalRect.y < self.globalRect.y:542 if element.globalRect.y < self.globalRect.y:
548 stop_y = start_y + element.implicitHeight543 self._show_more_elements_above()
549 else:544 else:
550 stop_y = start_y - element.implicitHeight545 self._show_more_elements_below()
551546
552 if platform.model() == 'Desktop':547 def _select_element(self, object_name):
553 # The drag on the desktop is done two fast, so we are left at548 try:
554 # the bottom or at the top of the list, sometimes missing the549 return self.select_single(objectName=object_name)
555 # element we are looking for.550 except dbus.StateNotFoundError:
556 # TODO: use the slow drag once it's implemented:551 # If the list is big, elements will only be created when we scroll
557 # https://bugs.launchpad.net/autopilot/+bug/1257055552 # them into view.
558 # --elopio - 2014-01-09553 self._scroll_to_top()
559 self.pointing_device.move(start_x, start_y)554 while not self.atYEnd:
560 self.pointing_device.press()555 self._show_more_elements_below()
561 self.pointing_device.move(stop_x, stop_y)556 try:
562 time.sleep(0.3)557 return self.select_single(objectName=object_name)
563 self.pointing_device.release()558 except dbus.StateNotFoundError:
564 else:559 pass
565 self.pointing_device.drag(start_x, start_y, stop_x, stop_y)560 raise ToolkitEmulatorException(
566561 'List element with objectName "{}" not found.'.format(
567 def _is_element_fully_visible(self, objectName):562 object_name))
563
564 @autopilot_logging.log_action(logger.info)
565 def _scroll_to_top(self):
566 x, y, width, height = self.globalRect
567 while not self.atYBeginning:
568 self._show_more_elements_above()
569
570 @autopilot_logging.log_action(logger.info)
571 def _show_more_elements_below(self):
572 if self.atYEnd:
573 raise ToolkitEmulatorException('There are no more elements below.')
574 else:
575 self._show_more_elements('below')
576
577 @autopilot_logging.log_action(logger.info)
578 def _show_more_elements_above(self):
579 if self.atYBeginning:
580 raise ToolkitEmulatorException('There are no more elements above.')
581 else:
582 self._show_more_elements('above')
583
584 def _show_more_elements(self, direction):
585 x, y, width, height = self.globalRect
586 start_x = stop_x = x + (width / 2)
587 # Start and stop just a little under the top of the list.
588 top = y + 5
589 bottom = y + height - 5
590 if direction == 'below':
591 start_y = bottom
592 stop_y = top
593 elif direction == 'above':
594 start_y = top
595 stop_y = bottom
596 else:
597 raise ToolkitEmulatorException(
598 'Invalid direction {}.'.format(direction))
599 self._slow_drag(start_x, stop_x, start_y, stop_y)
600 self.dragging.wait_for(False)
601 self.moving.wait_for(False)
602
603 def _slow_drag(self, start_x, stop_x, start_y, stop_y):
604 # If we drag too fast, we end up scrolling more than what we
605 # should, sometimes missing the element we are looking for.
606 self.pointing_device.drag(start_x, start_y, stop_x, stop_y, rate=5)
607
608 def _is_element_clickable(self, objectName):
609 """Return True if the center of the element is visible."""
568 element = self.select_single(objectName=objectName)610 element = self.select_single(objectName=objectName)
569 return (element.globalRect.y >= self.globalRect.y and611 element_center = element.globalRect.y + element.globalRect.height / 2
570 element.globalRect.y + element.globalRect.height <=612 return (element_center >= self.globalRect.y and
571 self.globalRect.y + self.globalRect.height)613 element_center <= self.globalRect.y + self.globalRect.height)
572614
573615
574class Empty(UbuntuUIToolkitEmulatorBase):616class Empty(UbuntuUIToolkitEmulatorBase):
575617
=== modified file 'tests/autopilot/ubuntuuitoolkit/tests/test_emulators.py'
--- tests/autopilot/ubuntuuitoolkit/tests/test_emulators.py 2014-01-13 15:23:25 +0000
+++ tests/autopilot/ubuntuuitoolkit/tests/test_emulators.py 2014-02-22 00:04:26 +0000
@@ -574,47 +574,6 @@
574 text: "No element clicked."574 text: "No element clicked."
575 }575 }
576576
577 ListModel {
578 id: testModel
579
580 ListElement {
581 objectName: "testListElement1"
582 label: "test list element 1"
583 }
584 ListElement {
585 objectName: "testListElement2"
586 label: "test list element 2"
587 }
588 ListElement {
589 objectName: "testListElement3"
590 label: "test list element 3"
591 }
592 ListElement {
593 objectName: "testListElement4"
594 label: "test list element 4"
595 }
596 ListElement {
597 objectName: "testListElement5"
598 label: "test list element 5"
599 }
600 ListElement {
601 objectName: "testListElement6"
602 label: "test list element 6"
603 }
604 ListElement {
605 objectName: "testListElement7"
606 label: "test list element 7"
607 }
608 ListElement {
609 objectName: "testListElement8"
610 label: "test list element 8"
611 }
612 ListElement {
613 objectName: "testListElement9"
614 label: "test list element 9"
615 }
616 }
617
618 ListView {577 ListView {
619 id: testListView578 id: testListView
620 objectName: "testListView"579 objectName: "testListView"
@@ -622,13 +581,13 @@
622 anchors.right: parent.right581 anchors.right: parent.right
623 height: column.height - clickedLabel.paintedHeight582 height: column.height - clickedLabel.paintedHeight
624 clip: true583 clip: true
625 model: testModel584 model: 20
626585
627 delegate: ListItem.Standard {586 delegate: ListItem.Standard {
628 text: model.label587 objectName: "testListElement%1".arg(index)
629 objectName: model.objectName588 text: "test list element %1".arg(index)
630 onClicked: clickedLabel.text = model.objectName589 onClicked: clickedLabel.text = objectName
631 height: units.gu(5)590 height: units.gu(5)
632 }591 }
633 }592 }
634 }593 }
@@ -648,32 +607,45 @@
648 self.assertIsInstance(self.list_view, emulators.QQuickListView)607 self.assertIsInstance(self.list_view, emulators.QQuickListView)
649608
650 def test_click_element(self):609 def test_click_element(self):
651 self.list_view.click_element('testListElement1')610 self.list_view.click_element('testListElement0')
652 self.assertEqual(self.label.text, 'testListElement1')611 self.assertEqual(self.label.text, 'testListElement0')
653612
654 def test_click_element_outside_view_below(self):613 def test_click_element_outside_view_below(self):
655 # Click the first element out of view to make sure we are not scrolling614 # Click the first element out of view to make sure we are not scrolling
656 # to the bottom at once.615 # to the bottom at once.
657 self.assertFalse(616 self.assertFalse(
658 self.list_view._is_element_fully_visible('testListElement5'))617 self.list_view._is_element_clickable('testListElement5'))
659618
660 self.list_view.click_element('testListElement5')619 self.list_view.click_element('testListElement5')
661 self.assertEqual(self.label.text, 'testListElement5')620 self.assertEqual(self.label.text, 'testListElement5')
662621
663 def test_click_element_outside_view_above(self):622 def test_click_element_outside_view_above(self):
664 # First we need to scroll to the 8th element in order for the 9th to be
665 # created.
666 self.list_view.click_element('testListElement8')
667 self.list_view.click_element('testListElement9')623 self.list_view.click_element('testListElement9')
668624
669 # Click the first element out of view to make sure we are not scrolling625 # Click the first element out of view to make sure we are not scrolling
670 # to the top at once.626 # to the top at once.
671 self.assertFalse(627 self.assertFalse(
672 self.list_view._is_element_fully_visible('testListElement4'))628 self.list_view._is_element_clickable('testListElement4'))
673629
674 self.list_view.click_element('testListElement4')630 self.list_view.click_element('testListElement4')
675 self.assertEqual(self.label.text, 'testListElement4')631 self.assertEqual(self.label.text, 'testListElement4')
676632
633 def test_click_element_not_created_at_start(self):
634 objectName = 'testListElement19'
635 self.assertRaises(
636 dbus.StateNotFoundError,
637 self.list_view.select_single,
638 objectName=objectName)
639 self.list_view.click_element(objectName)
640
641 def test_click_unexisting_element(self):
642 error = self.assertRaises(
643 emulators.ToolkitEmulatorException,
644 self.list_view.click_element,
645 'unexisting')
646 self.assertEqual(
647 str(error), 'List element with objectName "unexisting" not found.')
648
677649
678class SwipeToDeleteTestCase(tests.QMLStringAppTestCase):650class SwipeToDeleteTestCase(tests.QMLStringAppTestCase):
679651

Subscribers

People subscribed via source and target branches

to status/vote changes: