← Back to team overview

ubuntu-touch-coreapps-reviewers team mailing list archive

[Merge] lp:~nik90/ubuntu-clock-app/add-stopwatch-ap-tests into lp:ubuntu-clock-app

 

Nekhelesh Ramananthan has proposed merging lp:~nik90/ubuntu-clock-app/add-stopwatch-ap-tests into lp:ubuntu-clock-app with lp:~nik90/ubuntu-clock-app/fix-failing-ap-tests as a prerequisite.

Commit message:
Added stopwatch tests

Requested reviews:
  Jenkins Bot (ubuntu-core-apps-jenkins-bot): continuous-integration
  Ubuntu Clock Developers (ubuntu-clock-dev)
Related bugs:
  Bug #1490206 in Ubuntu Clock App: "[Autopilot] Test stopwatch feature"
  https://bugs.launchpad.net/ubuntu-clock-app/+bug/1490206

For more details, see:
https://code.launchpad.net/~nik90/ubuntu-clock-app/add-stopwatch-ap-tests/+merge/287919

Added stopwatch tests

IMPORTANT NOTE: In order to detect that stopwatchPage has fully loaded in Autopilot, it was necessary to rewrite the page switch code in MainPage.qml. Rest assured it isn't too much of a code change. That said, test the UX and see if it is *exactly* the same as before.
-- 
Your team Ubuntu Clock Developers is requested to review the proposed merge of lp:~nik90/ubuntu-clock-app/add-stopwatch-ap-tests into lp:ubuntu-clock-app.
=== modified file 'app/MainPage.qml'
--- app/MainPage.qml	2016-03-03 00:28:40 +0000
+++ app/MainPage.qml	2016-03-03 14:39:14 +0000
@@ -107,13 +107,42 @@
         }
     }
 
+
+
     ListView {
         id: listview
+        objectName: "pageListView"
+
+        // Property required only in autopilot to check if listitem has finished moving
+        property alias isMoving: moveAnimation.running
+
+        function moveToStopwatchPage() {
+            moveAnimation.moveTo(listview.originX + listview.width)
+            listview.currentIndex = 1
+        }
+
+        function moveToClockPage() {
+            moveAnimation.moveTo(listview.originX)
+            listview.currentIndex = 0
+        }
+
+        UbuntuNumberAnimation {
+            id: moveAnimation
+            objectName: "pageListViewAnimation"
+
+            target: listview
+            property: "contentX"
+            function moveTo(contentX) {
+                from = listview.contentX
+                to = contentX
+                start()
+            }
+        }
 
         // Show the stopwatch page on app startup if it is running
         Component.onCompleted: {
             if (stopwatchPage.isRunning) {
-                positionViewAtIndex(1, ListView.SnapPosition)
+                moveToStopwatchPage()
             }
         }
 
@@ -128,7 +157,5 @@
         orientation: ListView.Horizontal
         snapMode: ListView.SnapOneItem
         interactive: false
-        highlightMoveDuration: UbuntuAnimation.BriskDuration
-        highlightRangeMode: ListView.StrictlyEnforceRange
     }
 }

=== modified file 'app/components/HeaderNavigation.qml'
--- app/components/HeaderNavigation.qml	2016-02-29 12:42:02 +0000
+++ app/components/HeaderNavigation.qml	2016-03-03 14:39:14 +0000
@@ -31,15 +31,21 @@
         spacing: units.gu(2)
 
         ActionIcon {
+            id: clockNavigationButton
+            objectName: "clockNavigationButton"
+
             icon.name: "clock"
             icon.color: listview.currentIndex === 0 ? "#19b6ee" : "#5d5d5d" // #TODO: Replace with UbuntuColors.Blue and UbuntuColors.Slate after OTA-10
-            onClicked: listview.currentIndex = 0
+            onClicked: listview.moveToClockPage()
         }
         
         ActionIcon {
+            id: stopwatchNavigationButton
+            objectName: "stopwatchNavigationButton"
+
             icon.name: "stopwatch"
             icon.color: listview.currentIndex === 1 ? "#19b6ee" : "#5d5d5d" // #TODO: Replace with UbuntuColors.Blue and UbuntuColors.Slate after OTA-10
-            onClicked: listview.currentIndex = 1
+            onClicked:  listview.moveToStopwatchPage()
         }
     }
     

=== modified file 'app/stopwatch/CMakeLists.txt'
--- app/stopwatch/CMakeLists.txt	2015-08-25 01:02:54 +0000
+++ app/stopwatch/CMakeLists.txt	2016-03-03 14:39:14 +0000
@@ -1,5 +1,6 @@
 set(STOPWATCH_QML_JS_FILES
     LapListView.qml
+    LapsListDelegate.qml
     StopwatchFace.qml
     StopwatchPage.qml
 )

=== modified file 'app/stopwatch/LapListView.qml'
--- app/stopwatch/LapListView.qml	2016-02-26 10:00:54 +0000
+++ app/stopwatch/LapListView.qml	2016-03-03 14:39:14 +0000
@@ -20,11 +20,10 @@
 import Ubuntu.Components 1.3
 import Stopwatch 1.0
 
-UbuntuListView {
+ListView {
     id: lapListView
 
     clip: true
-    currentIndex: -1
 
     StopwatchFormatTime {
         id: stopwatchFormatTime
@@ -75,18 +74,18 @@
         }
     }
 
-    delegate: ListItem {
-        divider.visible: true
+    delegate: LapsListDelegate {
+        id: lapsListItem
+        objectName: "lapsListItem" + index
+
         divider.anchors.leftMargin: units.gu(2)
-        divider.anchors.right: parent.right
         divider.anchors.rightMargin: units.gu(2)
 
-        width: parent.width
-        anchors.horizontalCenter: parent.horizontalCenter
-
         leadingActions: ListItemActions {
             actions: [
                 Action {
+                    id: swipeDeleteAction
+                    objectName: "swipeDeleteAction"
                     iconName: "delete"
                     onTriggered: {
                         stopwatchEngine.removeLap(index)
@@ -95,48 +94,10 @@
             ]
         }
 
-        Row {
-            anchors {
-                left: parent.left
-                right: parent.right
-                verticalCenter: parent.verticalCenter
-                leftMargin: units.gu(3)
-                rightMargin: units.gu(2)
-            }
-
-            Label {
-                text: "#%1".arg(Number(count - index).toLocaleString(Qt.locale(), "f", 0))
-                width: parent.width / 5
-                horizontalAlignment: Text.AlignLeft
-            }
-
-            Item {
-                width: 2* parent.width / 5
-                height: childrenRect.height
-                Row {
-                    anchors.horizontalCenter: parent.horizontalCenter
-                    Label {
-                        text: stopwatchFormatTime.lapTimeToString(model.laptime) + "."
-                    }
-                    Label {
-                        text: stopwatchFormatTime.millisToString(model.laptime)
-                    }
-                }
-            }
-
-            Item {
-                width: 2 * parent.width / 5
-                height: childrenRect.height
-                Row {
-                    anchors.right: parent.right
-                    Label {
-                        text: stopwatchFormatTime.lapTimeToString(model.totaltime) + "."
-                    }
-                    Label {
-                        text: stopwatchFormatTime.millisToString(model.totaltime)
-                    }
-                }
-            }
-        }
+        indexLabel: "#%1".arg(Number(count - index).toLocaleString(Qt.locale(), "f", 0))
+        lapTimeLabel: stopwatchFormatTime.lapTimeToString(model.laptime) + "."
+        lapMilliTimeLabel: stopwatchFormatTime.millisToString(model.laptime)
+        totalTimeLabel: stopwatchFormatTime.lapTimeToString(model.totaltime) + "."
+        totalMilliTimeLabel: stopwatchFormatTime.millisToString(model.totaltime)
     }
 }

=== added file 'app/stopwatch/LapsListDelegate.qml'
--- app/stopwatch/LapsListDelegate.qml	1970-01-01 00:00:00 +0000
+++ app/stopwatch/LapsListDelegate.qml	2016-03-03 14:39:14 +0000
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2016 Canonical Ltd
+ *
+ * This file is part of Ubuntu Clock App
+ *
+ * Ubuntu Clock App is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * Ubuntu Clock App is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+import QtQuick 2.4
+import Ubuntu.Components 1.3
+
+ListItem {
+    id: lapsListItem
+
+    property string indexLabel
+    property string lapTimeLabel
+    property string lapMilliTimeLabel
+    property string totalTimeLabel
+    property string totalMilliTimeLabel
+
+    Row {
+        anchors {
+            left: parent.left
+            right: parent.right
+            verticalCenter: parent.verticalCenter
+            leftMargin: units.gu(3)
+            rightMargin: units.gu(2)
+        }
+
+        Label {
+            id: _indexLabel
+            text: indexLabel
+            width: parent.width / 5
+            horizontalAlignment: Text.AlignLeft
+        }
+
+        Item {
+            id: lapTimeContainer
+            width: 2* parent.width / 5
+            height: childrenRect.height
+            Row {
+                anchors.horizontalCenter: parent.horizontalCenter
+                Label {
+                    id: _lapTimeLabel
+                    text: lapTimeLabel
+                }
+                Label {
+                    id: _lapMilliTimeLabel
+                    text: lapMilliTimeLabel
+                }
+            }
+        }
+
+        Item {
+            width: 2 * parent.width / 5
+            height: childrenRect.height
+            Row {
+                anchors.right: parent.right
+                Label {
+                    id: _totalTimeLabel
+                    text: totalTimeLabel
+                }
+                Label {
+                    id: _totalMilliTimeLabel
+                    text: totalMilliTimeLabel
+                }
+            }
+        }
+    }
+}

=== modified file 'app/stopwatch/StopwatchFace.qml'
--- app/stopwatch/StopwatchFace.qml	2016-03-02 12:04:48 +0000
+++ app/stopwatch/StopwatchFace.qml	2016-03-03 14:39:14 +0000
@@ -35,6 +35,7 @@
 
     Label {
         id: time
+        objectName: "stopwatchTime"
 
         text: stopwatchFormatTime.millisToTimeString(milliseconds, true)
         font.pixelSize: units.dp(36)
@@ -44,6 +45,7 @@
 
     Label {
         id: miliseconds
+        objectName: "stopwatchMilliseconds"
 
         text: stopwatchFormatTime.millisToString(milliseconds)
         textSize: Label.Large

=== modified file 'app/stopwatch/StopwatchPage.qml'
--- app/stopwatch/StopwatchPage.qml	2016-02-25 22:16:54 +0000
+++ app/stopwatch/StopwatchPage.qml	2016-03-03 14:39:14 +0000
@@ -71,7 +71,8 @@
         }
 
         Button {
-            id: stopButton
+            id: startStopButton
+            objectName: "startAndStopButton"
 
             width: parent.width / 2 - units.gu(1)
             height: units.gu(4)
@@ -94,6 +95,7 @@
 
         Button {
             id: lapButton
+            objectName: "lapAndClearButton"
 
             text: stopwatchEngine.running ? i18n.tr("Lap") : i18n.tr("Clear")
             width: parent.width / 2 - units.gu(1)
@@ -138,6 +140,7 @@
         id: lapListViewComponent
         LapListView {
             id: lapListView
+            objectName: "lapsList"
             model: stopwatchEngine
         }
     }

=== modified file 'debian/changelog'
--- debian/changelog	2016-03-03 11:58:53 +0000
+++ debian/changelog	2016-03-03 14:39:14 +0000
@@ -4,6 +4,7 @@
   * Dynamic loading of ListView in ExpandableListItem
   * Removed all vertical positioning overrides of trailing icon in ListItem.
   * Fixed failing autopilot tests in trunk (LP: #1552489)
+  * Added Stopwatch autopilot tests (LP: #1490206)
 
  -- Nekhelesh <krnekhelesh@nik90-laptop>  Wed, 02 Mar 2016 19:30:48 +0100
 

=== modified file 'tests/autopilot/ubuntu_clock_app/__init__.py'
--- tests/autopilot/ubuntu_clock_app/__init__.py	2016-03-03 07:02:42 +0000
+++ tests/autopilot/ubuntu_clock_app/__init__.py	2016-03-03 14:39:14 +0000
@@ -20,7 +20,7 @@
 
 from autopilot import logging as autopilot_logging
 from autopilot.introspection import dbus
-from testtools.matchers import GreaterThan
+from testtools.matchers import (NotEquals, Equals, GreaterThan)
 
 from ubuntuuitoolkit import (
     MainView, UbuntuUIToolkitCustomProxyObjectBase, pickers, UCListItem)
@@ -83,6 +83,18 @@
         return self.wait_select_single("WorldCityList",
                                        objectName="worldCityList")
 
+    @autopilot_logging.log_action(logger.info)
+    def open_stopwatch(self):
+        """Open the Stopwatch Page.
+
+        :return: the Stopwatch Page.
+
+        """
+        mainPage = self.get_main_page()
+        mainPage.press_header_navigation_button(
+            'stopwatchNavigationButton')
+        return self.wait_select_single(StopwatchPage)
+
 
 class Page(UbuntuUIToolkitCustomProxyObjectBase):
     """Autopilot helper for Pages."""
@@ -120,6 +132,153 @@
             logger.error('BottomEdge element not found.')
             raise
 
+    def press_header_navigation_button(self, button_object_name):
+        """Press the passed custom navigation button
+
+        :param button_object_name: Object name of navigation button
+
+        """
+        navigation_button = self.wait_select_single(
+            'ActionIcon', objectName=button_object_name)
+        self.pointing_device.click_object(navigation_button)
+        page_list_view = self.wait_select_single(
+            'QQuickListView', objectName="pageListView")
+        page_list_view.isMoving.wait_for(False)
+
+
+class StopwatchPage(Page):
+    """Autopilot helper for the Stopwatch page."""
+
+    @autopilot_logging.log_action(logger.info)
+    def start_stopwatch(self):
+        self._click_start_stop_button()
+
+        try:
+            self._get_start_stop_button().text.wait_for("Stop")
+            self._get_lap_clear_button().text.wait_for("Lap")
+            self._get_stopwatch_time().text.wait_for(
+                NotEquals("00:00:00"))
+            self._get_stopwatch_milliseconds().text.wait_for(
+                NotEquals("000"))
+        except AssertionError:
+            raise ClockEmulatorException(
+                'Incorrect stopwatch run state')
+
+    @autopilot_logging.log_action(logger.info)
+    def stop_stopwatch(self):
+        self._click_start_stop_button()
+
+        try:
+            self._get_start_stop_button().text.wait_for("Resume")
+            self._get_lap_clear_button().text.wait_for("Clear")
+            self._get_stopwatch_time().text.wait_for(
+                NotEquals("00:00:00"))
+            self._get_stopwatch_milliseconds().text.wait_for(
+                NotEquals("000"))
+        except AssertionError:
+            raise ClockEmulatorException(
+                'Incorrect stopwatch pause state')
+
+    @autopilot_logging.log_action(logger.info)
+    def clear_stopwatch(self):
+        self._click_lap_clear_button()
+
+        try:
+            self._get_start_stop_button().text.wait_for("Start")
+            self._get_stopwatch_time().text.wait_for(
+                Equals("00:00:00"))
+            self._get_stopwatch_milliseconds().text.wait_for(
+                Equals("000"))
+        except AssertionError:
+            raise ClockEmulatorException(
+                'Invalid stopwatch clear state')
+
+    @autopilot_logging.log_action(logger.info)
+    def add_lap(self):
+        old_count = self._get_laps_count()
+        self._click_lap_clear_button()
+
+        try:
+            self._get_laps_list_view().count.wait_for(
+                Equals(old_count + 1))
+        except AssertionError:
+            raise ClockEmulatorException(
+                'Laps count did not increase on pressing the add lap \
+                button')
+
+    @autopilot_logging.log_action(logger.info)
+    def delete_lap(self, index):
+        old_count = self._get_laps_count()
+        laps_list = self._get_laps_list_view()
+
+        lap = laps_list.wait_select_single(
+            "LapsListDelegate", objectName="lapsListItem{}".format(index))
+        lap.click_remove_action()
+
+        try:
+            self._get_laps_list_view().count.wait_for(
+                Equals(old_count - 1))
+        except AssertionError:
+            raise ClockEmulatorException(
+                'Laps count did not decrease on deleting the lap')
+
+    def _get_laps_count(self):
+        return int(self._get_laps_list_view().count)
+
+    def _get_laps_list_view(self):
+        return self.wait_select_single("QQuickListView",
+                                       objectName="lapsList")
+
+    @autopilot_logging.log_action(logger.info)
+    def clean_up_test(self):
+        if self._get_start_stop_button().text == "Stop":
+            self._click_start_stop_button()
+
+        if self._get_lap_clear_button().text == "Clear":
+            self._click_lap_clear_button()
+
+    def _get_stopwatch_time(self):
+        """Return the stopwatch time object"""
+        stopwatch_time = self.wait_select_single(
+            "UCLabel", objectName="stopwatchTime")
+        return stopwatch_time
+
+    def _get_stopwatch_milliseconds(self):
+        """Return the stopwatch milliseconds object"""
+        stopwatch_milliseconds = self.wait_select_single(
+            "UCLabel", objectName="stopwatchMilliseconds")
+        return stopwatch_milliseconds
+
+    def _get_start_stop_button(self):
+        """Return the start/stop button"""
+        start_stop_button = self.wait_select_single(
+            "Button", objectName="startAndStopButton")
+        return start_stop_button
+
+    def _get_lap_clear_button(self):
+        """Return the lap/clear button"""
+        lap_clear_button = self.wait_select_single(
+            "Button", objectName="lapAndClearButton")
+        return lap_clear_button
+
+    def _click_start_stop_button(self):
+        """Press the start/stop button"""
+        start_stop_button = self._get_start_stop_button()
+        self.pointing_device.click_object(start_stop_button)
+
+    def _click_lap_clear_button(self):
+        """Press the lap/clear button"""
+        lap_clear_button = self._get_lap_clear_button()
+        self.pointing_device.click_object(lap_clear_button)
+
+
+class LapsListDelegate(UCListItem):
+    """Autopilot helper for laps list delegate"""
+
+    def click_remove_action(self):
+        return self.trigger_leading_action('swipeDeleteAction',
+                                           self.wait_until_destroyed)
+
 
 class ClockPage(Page):
     """Autopilot helper for the Clock page."""

=== modified file 'tests/autopilot/ubuntu_clock_app/tests/test_alarm.py'
--- tests/autopilot/ubuntu_clock_app/tests/test_alarm.py	2016-03-03 07:02:42 +0000
+++ tests/autopilot/ubuntu_clock_app/tests/test_alarm.py	2016-03-03 14:39:14 +0000
@@ -22,12 +22,13 @@
 
 from autopilot.matchers import Eventually
 from testtools.matchers import Equals
+
 from ubuntu_clock_app.tests import ClockAppTestCase
 
 
 class TestAlarm(ClockAppTestCase):
-
     """Tests the alarm page features"""
+
     scenarios = [
         ('random',
             {'alarm_name': 'Random days Alarm Test',
@@ -55,7 +56,7 @@
     ]
 
     def setUp(self):
-        """ This is needed to wait for the application to start.
+        """This is needed to wait for the application to start.
 
         In the testfarm, the application may take some time to show up.
 

=== modified file 'tests/autopilot/ubuntu_clock_app/tests/test_clock.py'
--- tests/autopilot/ubuntu_clock_app/tests/test_clock.py	2016-03-03 00:28:40 +0000
+++ tests/autopilot/ubuntu_clock_app/tests/test_clock.py	2016-03-03 14:39:14 +0000
@@ -27,7 +27,6 @@
 
 
 class TestClock(ClockAppTestCase):
-
     """Test the clock page features."""
 
     def setUp(self):

=== added file 'tests/autopilot/ubuntu_clock_app/tests/test_stopwatch.py'
--- tests/autopilot/ubuntu_clock_app/tests/test_stopwatch.py	1970-01-01 00:00:00 +0000
+++ tests/autopilot/ubuntu_clock_app/tests/test_stopwatch.py	2016-03-03 14:39:14 +0000
@@ -0,0 +1,63 @@
+# Copyright (C) 2016 Canonical Ltd
+#
+# This file is part of Ubuntu Clock App
+#
+# Ubuntu Clock App is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 3 as
+# published by the Free Software Foundation.
+#
+# Ubuntu Clock App is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Tests for the Clock App, stopwatch page.
+"""
+
+from __future__ import absolute_import
+
+from autopilot.matchers import Eventually
+from testtools.matchers import Equals
+
+from ubuntu_clock_app.tests import ClockAppTestCase
+
+
+class TestStopwatch(ClockAppTestCase):
+    """Tests the stopwatch feature"""
+
+    def setUp(self):
+        """This is needed to wait for the application to start.
+
+        In the testfarm, the application may take some time to show up.
+
+        """
+        super(TestStopwatch, self).setUp()
+        self.assertThat(
+            self.app.main_view.visible, Eventually(Equals(True)))
+
+        self.page = self.app.main_view.open_stopwatch()
+
+    def test_pressing_gui_button_starts_stops_clears_stopwatch(self):
+        """Test to check if stopwatch can be started, stopped and
+        cleared using the UI buttons"""
+
+        self.page.start_stopwatch()
+        self.page.stop_stopwatch()
+        self.page.clear_stopwatch()
+
+    def test_pressing_lap_button_adds_laps(self):
+        """Test to check if stopwatch laps can be created"""
+        self.page.start_stopwatch()
+        self.page.add_lap()
+        self.page.clean_up_test()
+
+    def test_swipe_delete_button_deletes_laps(self):
+        """Test to check if laps can be deleted by swiping right"""
+        self.page.start_stopwatch()
+        self.page.add_lap()
+        self.page.delete_lap(0)
+        self.page.clean_up_test()


Follow ups