Merge lp:~carla-sella/ubuntu-clock-app/add-alarm-test into lp:ubuntu-clock-app
- add-alarm-test
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 38 |
Proposed branch: | lp:~carla-sella/ubuntu-clock-app/add-alarm-test |
Merge into: | lp:ubuntu-clock-app |
Prerequisite: | lp:~nik90/ubuntu-clock-app/implement-change-time-settings |
Diff against target: |
1268 lines (+799/-218) 20 files modified
README.autopilot (+45/-0) app/alarm/AlarmLabel.qml (+2/-0) app/alarm/AlarmList.qml (+7/-0) app/alarm/AlarmPage.qml (+2/-0) app/alarm/AlarmRepeat.qml (+4/-0) app/alarm/AlarmSound.qml (+3/-0) app/alarm/EditAlarmPage.qml (+5/-0) app/tests/autopilot/run (+0/-11) app/tests/autopilot/ubuntu-clock-app/__init__.py (+0/-132) app/tests/autopilot/ubuntu-clock-app/main/__init__.py (+0/-1) app/tests/autopilot/ubuntu-clock-app/main/test_main.py (+0/-23) app/tests/unit/tst_hellocomponent.qml (+0/-49) manifest.json (+5/-2) tests/autopilot/run (+11/-0) tests/autopilot/ubuntu_clock_app/__init__.py (+18/-0) tests/autopilot/ubuntu_clock_app/emulators.py (+395/-0) tests/autopilot/ubuntu_clock_app/tests/__init__.py (+125/-0) tests/autopilot/ubuntu_clock_app/tests/test_alarm.py (+84/-0) tests/autopilot/ubuntu_clock_app/tests/test_clock.py (+44/-0) tests/unit/tst_hellocomponent.qml (+49/-0) |
To merge this branch: | bzr merge lp:~carla-sella/ubuntu-clock-app/add-alarm-test |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu Phone Apps Jenkins Bot | continuous-integration | Needs Fixing | |
Nekhelesh Ramananthan | Approve | ||
Review via email: mp+229084@code.launchpad.net |
Commit message
Autopilot test for clock/reboot app
Description of the change
Carla Sella (carla-sella) wrote : | # |
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:53
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:54
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:55
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:56
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Nekhelesh Ramananthan (nik90) wrote : | # |
I took the README.autopilot and improved it further at http://
Nekhelesh Ramananthan (nik90) wrote : | # |
518 +# Copyright (C) 2013, 2014 Canonical Ltd
519 +#
520 +# This program is free software: you can redistribute it and/or modify
521 +# it under the terms of the GNU General Public License version 3 as
522 +# published by the Free Software Foundation.
523 +#
524 +# This program is distributed in the hope that it will be useful,
525 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
526 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
527 +# GNU General Public License for more details.
528 +#
529 +# You should have received a copy of the GNU General Public License
530 +# along with this program. If not, see <http://
531 +#
532 +# Authored by: Renato Araujo Oliveira Filho <email address hidden>
Please replace all copyright headers with the new ones we added in the QML files please to maintain consistency throughout the source package.
Nekhelesh Ramananthan (nik90) wrote : | # |
563 +from ubuntuuitoolkit import emulators as toolkit_emulators, pickers
I believe balloons submitted a merge proposal against the old clock app where he switches the import statement to
import ubuntuuitoolkit
You can find his MP at https:/
Nekhelesh Ramananthan (nik90) wrote : | # |
729 + if mode == 'time':
730 + mode_value = 'Hours|Minutes'
731 + else:
732 + mode_value = 'Years|Months|Days'
733 + picker = self.wait_
734 + pickers.DatePicker, mode=mode_value, visible=True)
735 + if mode_value == 'Hours|Minutes':
736 + picker.
737 + else:
738 + picker.
Hmm, I am not sure why this is required. For the clock app, we will always only show the time picker, so can't we assume that the mode is time and proceed with that? Unless I am missing something here.
Nicholas Skaggs (nskaggs) wrote : | # |
> 563 +from ubuntuuitoolkit import emulators as toolkit_emulators, pickers
>
> I believe balloons submitted a merge proposal against the old clock app where
> he switches the import statement to
>
> import ubuntuuitoolkit
>
> You can find his MP at https:/
> /switch-
> for the clock app, it would be best if we could do this from the start. Can
> you make the appropriate changes? Remember that whereever you import the
> ubuntu emulator, you will need to make changes there as well. Best to look at
> balloons's MP to see what needs to be done.
I would not hold the MP on this, but yes, it's simply changing the imports a little.
Nekhelesh Ramananthan (nik90) wrote : | # |
640 +class Page11(Page):
641 +
642 + """Autopilot helper for the Alarm page."""
Why is this Page11 and not AlarmPage?
Nekhelesh Ramananthan (nik90) wrote : | # |
803 + def _select_
804 + """ function for selecting the day passed to the function.
805 +
806 + :param index: the day to be selected
807 +
808 + """
809 + dayCheckbox = self.wait_
810 + 'CheckBox', objectName=
811 + if not dayCheckbox.
812 + self.pointing_
813 +
814 + @autopilot_
815 + def unselect_
816 + """ function for unselecting already selected days. """
817 + for index in range(self.
818 + if self.wait_
819 + 'CheckBox', objectName=
820 + .checked:
821 + self.pointing_
822 + 'CheckBox', objectName=
823 + break
In these 2 functions, you are using the IF loop to check if the switch is checked or not. Why not use the Ubuntu SDK helpers for this? http://
This would make it as simple as,
dayCheckbox.check()
or
dayCheckbox.
Nekhelesh Ramananthan (nik90) wrote : | # |
848 + def _select_
849 + """ function for selecting the sound passed to the function.
850 +
851 + :param index: the sound to be selected
852 +
853 + """
854 + soundCheckbox = self.wait_
855 + 'CheckBox', objectName=
856 + if not soundCheckbox.
857 + self.pointing_
Same here. It would be better to use the SDK helper functions.
Carla Sella (carla-sella) wrote : | # |
Ok done.
Carla Sella (carla-sella) wrote : | # |
> 640 +class Page11(Page):
> 641 +
> 642 + """Autopilot helper for the Alarm page."""
>
> Why is this Page11 and not AlarmPage?
Because in autopilot vis I see Page11: https:/
Do you want me to change it in AlarmPage anyway ?
Nekhelesh Ramananthan (nik90) wrote : | # |
> > 640 +class Page11(Page):
> > 641 +
> > 642 + """Autopilot helper for the Alarm page."""
> >
> > Why is this Page11 and not AlarmPage?
>
> Because in autopilot vis I see Page11:
> https:/
>
> Do you want me to change it in AlarmPage anyway ?
Lets give it a try, and see if it recognizes AlarmPage instead of Page11. If it doesn't work, we can stick to Page11. The reason being in the SDK I saw Page10, Page11 etc. and I don't want this test to break everytime they make a change in the SDK.
Carla Sella (carla-sella) wrote : | # |
> > > 640 +class Page11(Page):
> > > 641 +
> > > 642 + """Autopilot helper for the Alarm page."""
> > >
> > > Why is this Page11 and not AlarmPage?
> >
> > Because in autopilot vis I see Page11:
> > https:/
> >
> > Do you want me to change it in AlarmPage anyway ?
>
> Lets give it a try, and see if it recognizes AlarmPage instead of Page11. If
> it doesn't work, we can stick to Page11. The reason being in the SDK I saw
> Page10, Page11 etc. and I don't want this test to break everytime they make a
> change in the SDK.
Nope, if I use AlarmPage I get errors, I've tried various ways. Maybe it will work if I change the code, but not sure you want me to change quite abit of it.
Carla Sella (carla-sella) wrote : | # |
@Nik: only skipping the test unless model is desktop is missing, but cannot recall the skip syntax and cannot seem to find it using google.
Can you help ?
Thanks.
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:57
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Carla Sella (carla-sella) wrote : | # |
Ok so now I think I got everything, also skipping the test if not Desktop model.
Nekhelesh Ramananthan (nik90) wrote : | # |
> > > > 640 +class Page11(Page):
> > > > 641 +
> > > > 642 + """Autopilot helper for the Alarm page."""
> > > >
> > > > Why is this Page11 and not AlarmPage?
> > >
> > > Because in autopilot vis I see Page11:
> > > https:/
> > >
> > > Do you want me to change it in AlarmPage anyway ?
> >
> > Lets give it a try, and see if it recognizes AlarmPage instead of Page11. If
> > it doesn't work, we can stick to Page11. The reason being in the SDK I saw
> > Page10, Page11 etc. and I don't want this test to break everytime they make
> a
> > change in the SDK.
>
> Nope, if I use AlarmPage I get errors, I've tried various ways. Maybe it will
> work if I change the code, but not sure you want me to change quite abit of
> it.
No if its too much work leave it, its fine.
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:58
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Nekhelesh Ramananthan (nik90) wrote : | # |
Thanks for the fixes. Looks better. Some more small ones left,
527 +# -#- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -#-
528 +#
529 +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
963 +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
964 +#
965 +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
966 +#
1098 +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
1099 +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
Duplicated lines
548 +#
549 +# Authored by: Renato Araujo Oliveira Filho <email address hidden>
575 +# Authored by: Nekhelesh Ramananthan <email address hidden>
576 +# Nicholas Skaggs <email address hidden>
Remove these as with the new copyright headers, we don't anymore include these.
Please check if there any other places in this MP where the above 2 issues are there. I might have missed some.
Nekhelesh Ramananthan (nik90) wrote : | # |
1150 + def test_add_
This test needs to be renamed to,
def test_add_
In the new clock app, we haven't added support yet for recurring alarms. All the alarms created are recurring alarms by default. In the next MP, we can make this test to be specific like weekend, weekday alarms etc etc.
Nekhelesh Ramananthan (nik90) wrote : | # |
1148 + @unittest.
1149 + "datepicker does not work correctly on device")
1150 + def test_add_
1151 + """Test to check if a single type alarm is saved properly
Here can you add a TODO comment explaining that due to bug #https:/
Nekhelesh Ramananthan (nik90) wrote : | # |
1006 + """A common test case class that provides several useful methods for
1007 + calendar-app tests.
This should be clock-app tests
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:59
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Carla Sella (carla-sella) wrote : | # |
Nik, hope eveything is ok now.
Nekhelesh Ramananthan (nik90) wrote : | # |
lgtm! Nice work!
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:59
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Nicholas Skaggs (nskaggs) wrote : | # |
Carla, in the readme I would mention running things with autopilot3, instead of autopilot. If you haven't run autopilot3 vis, you might be in for a surprise as it has search and some other niceties that autopilot vis doesn't have.
Also, for autopkg this line can be simplified:
adt-run ubuntu-clock-app --click=
to
adt-run ubuntu-clock-app --click=
Carla Sella (carla-sella) wrote : | # |
Nicholas, I made the changes to README.autopilot as you asked but I left out autopiolot3 vis.
If I run:
autopilot3 vis
I get:
usage: autopilot3 [-h] [-v] {run,list,launch} ...
autopilot3: error: argument mode: invalid choice: 'vis' (choose from 'run', 'list', 'launch')
Am I missing something ?
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:61
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Carla Sella (carla-sella) wrote : | # |
Got it! and fixed it :-).
I was missing python3-
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:62
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Nekhelesh Ramananthan (nik90) wrote : | # |
A small nitpick but could you add python3-
Carla Sella (carla-sella) wrote : | # |
Said and done :P.
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:63
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Nicholas Skaggs (nskaggs) wrote : | # |
> Nicholas, I made the changes to README.autopilot as you asked but I left out
> autopiolot3 vis.
> If I run:
>
> autopilot3 vis
>
> I get:
>
> usage: autopilot3 [-h] [-v] {run,list,launch} ...
> autopilot3: error: argument mode: invalid choice: 'vis' (choose from 'run',
> 'list', 'launch')
>
>
> Am I missing something ?
Carla, yes python3-
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Preview Diff
1 | === added file 'README.autopilot' |
2 | --- README.autopilot 1970-01-01 00:00:00 +0000 |
3 | +++ README.autopilot 2014-08-04 19:00:38 +0000 |
4 | @@ -0,0 +1,45 @@ |
5 | +# Running Autopilot tests |
6 | + |
7 | +Ubuntu Clock App follows a test driven development where autopilot tests are run before every merge into trunk. If you are submitting your bugfix/patch to the clock app, please follow the following steps below to ensure that all tests pass before proposing a merge request. |
8 | + |
9 | +If you are looking for more info about Autopilot or writing AP tests for the clock app, here are some useful links to help you, |
10 | + |
11 | +- http://developer.ubuntu.com/api/devel/ubuntu-14.10/python/autopilot/ |
12 | +- http://developer.ubuntu.com/api/devel/ubuntu-14.10/python/autopilot-emulator/ |
13 | + |
14 | +## Prerequisites |
15 | + |
16 | +Install the following autopilot packages required to run the tests, |
17 | +$ sudo apt-get install python-autopilot libautopilot-qt ubuntu-ui-toolkit-autopilot python3-autopilot-vis |
18 | + |
19 | + |
20 | +#### Running tests on the desktop |
21 | + |
22 | +Using terminal: |
23 | + |
24 | +1. Branch the clock app code, |
25 | + $ bzr branch lp:ubuntu-clock-app/reboot |
26 | + |
27 | +2. Navigate to the tests/autopilot directory. |
28 | + $ cd ubuntu-clock-app/reboot/tests/autopilot |
29 | + |
30 | +3. run all tests. |
31 | + $ autopilot3 run -vv ubuntu_clock_app |
32 | + |
33 | + to list all tests: |
34 | + $ autopilot3 list ubuntu_clock_app |
35 | + |
36 | + To run only one test (for instance: test_add_single_type_alarm_must_add_to_alarm_list in TestAlarm.py): |
37 | + $ autopilot3 run -vv ubuntu_clock_app.tests.test_alarm.TestAlarm.test_add_single_type_alarm_must_add_to_alarm_list |
38 | + |
39 | + Debugging tests using autopilot vis |
40 | + $ autopilot3 launch -i Qt qmlscene ../../app/ubuntu-clock-app.qml -I ../../builddir/backend/ |
41 | + $ autopilot3 vis |
42 | + |
43 | + |
44 | +#### Running tests on device or emulator: |
45 | + |
46 | +Using autopkg: |
47 | + |
48 | +1. navigate to the directory where the ubuntu-clock-app branch is and run: |
49 | + $ adt-run ubuntu-clock-app --click=com.ubuntu.clock.devel --- ssh -s adb |
50 | |
51 | === modified file 'app/alarm/AlarmLabel.qml' |
52 | --- app/alarm/AlarmLabel.qml 2014-07-17 12:21:45 +0000 |
53 | +++ app/alarm/AlarmLabel.qml 2014-08-04 19:00:38 +0000 |
54 | @@ -21,6 +21,7 @@ |
55 | |
56 | Page { |
57 | id: _alarmLabelPage |
58 | + objectName: "alarmLabelPage" |
59 | |
60 | visible: false |
61 | title: i18n.tr("Label") |
62 | @@ -44,6 +45,7 @@ |
63 | |
64 | TextField { |
65 | id: _labelEntry |
66 | + objectName: "labelEntry" |
67 | text: alarm.message |
68 | width: parent.width |
69 | } |
70 | |
71 | === modified file 'app/alarm/AlarmList.qml' |
72 | --- app/alarm/AlarmList.qml 2014-07-17 12:21:45 +0000 |
73 | +++ app/alarm/AlarmList.qml 2014-08-04 19:00:38 +0000 |
74 | @@ -58,14 +58,18 @@ |
75 | |
76 | Column { |
77 | id: alarmList |
78 | + objectName: 'alarmList' |
79 | anchors.fill: parent |
80 | |
81 | Repeater { |
82 | model: alarmListFlickable.model |
83 | + objectName: "alarmListRepeater" |
84 | ListItem.Base { |
85 | + objectName: "alarm" + index |
86 | |
87 | Label { |
88 | id: alarmTime |
89 | + objectName: "listAlarmTime" + index |
90 | |
91 | anchors { |
92 | top: alarmDetailsColumn.top |
93 | @@ -89,6 +93,7 @@ |
94 | |
95 | Label { |
96 | id: alarmLabel |
97 | + objectName: "listAlarmLabel" + index |
98 | |
99 | text: message |
100 | fontSize: "medium" |
101 | @@ -98,6 +103,7 @@ |
102 | |
103 | Label { |
104 | id: alarmSubtitle |
105 | + objectName: "listAlarmSubtitle" + index |
106 | |
107 | fontSize: "xx-small" |
108 | width: parent.width |
109 | @@ -108,6 +114,7 @@ |
110 | |
111 | Switch { |
112 | id: alarmStatus |
113 | + objectName: "listAlarmStatus" + index |
114 | |
115 | anchors { |
116 | right: parent.right |
117 | |
118 | === modified file 'app/alarm/AlarmPage.qml' |
119 | --- app/alarm/AlarmPage.qml 2014-07-17 12:21:45 +0000 |
120 | +++ app/alarm/AlarmPage.qml 2014-08-04 19:00:38 +0000 |
121 | @@ -22,10 +22,12 @@ |
122 | |
123 | Page { |
124 | title: "Alarms" |
125 | + objectName: 'AlarmPage' |
126 | |
127 | flickable: null |
128 | |
129 | head.actions: Action { |
130 | + objectName: "addAlarmAction" |
131 | iconName: "add" |
132 | text: i18n.tr("Alarm") |
133 | onTriggered: { |
134 | |
135 | === modified file 'app/alarm/AlarmRepeat.qml' |
136 | --- app/alarm/AlarmRepeat.qml 2014-07-17 12:21:45 +0000 |
137 | +++ app/alarm/AlarmRepeat.qml 2014-08-04 19:00:38 +0000 |
138 | @@ -22,6 +22,7 @@ |
139 | |
140 | Page { |
141 | id: _alarmRepeatPage |
142 | + objectName: "alarmRepeatPage" |
143 | |
144 | visible: false |
145 | title: i18n.tr("Repeat") |
146 | @@ -75,12 +76,14 @@ |
147 | |
148 | Repeater { |
149 | id: _alarmDays |
150 | + objectName: 'alarmDays' |
151 | |
152 | model: daysModel |
153 | |
154 | ListItem.Standard { |
155 | Label { |
156 | id: _alarmDay |
157 | + objectName: 'alarmDay' + index |
158 | |
159 | anchors { |
160 | left: parent.left |
161 | @@ -93,6 +96,7 @@ |
162 | } |
163 | |
164 | control: Switch { |
165 | + objectName: 'daySwitch' + index |
166 | checked: (alarm.daysOfWeek & flag) == flag |
167 | onCheckedChanged: { |
168 | if (checked) { |
169 | |
170 | === modified file 'app/alarm/AlarmSound.qml' |
171 | --- app/alarm/AlarmSound.qml 2014-07-17 12:21:45 +0000 |
172 | +++ app/alarm/AlarmSound.qml 2014-08-04 19:00:38 +0000 |
173 | @@ -52,6 +52,7 @@ |
174 | |
175 | Repeater { |
176 | id: _alarmSounds |
177 | + objectName: "alarmSounds" |
178 | |
179 | model: _soundModel |
180 | |
181 | @@ -64,6 +65,7 @@ |
182 | |
183 | Label { |
184 | id: _soundName |
185 | + objectName: "soundName" + index |
186 | |
187 | anchors { |
188 | left: parent.left |
189 | @@ -77,6 +79,7 @@ |
190 | |
191 | CheckBox { |
192 | id: _soundStatus |
193 | + objectName: "soundStatus" + index |
194 | |
195 | anchors { |
196 | right: parent.right |
197 | |
198 | === modified file 'app/alarm/EditAlarmPage.qml' |
199 | --- app/alarm/EditAlarmPage.qml 2014-07-28 14:25:00 +0000 |
200 | +++ app/alarm/EditAlarmPage.qml 2014-08-04 19:00:38 +0000 |
201 | @@ -25,6 +25,7 @@ |
202 | |
203 | Page { |
204 | id: _addAlarmPage |
205 | + objectName: "AddAlarmPage" |
206 | |
207 | // Property to determine if this is a new/saved alarm |
208 | property bool isNewAlarm: true |
209 | @@ -47,6 +48,7 @@ |
210 | |
211 | actions: Action { |
212 | iconName: "ok" |
213 | + objectName: "saveAlarmAction" |
214 | text: i18n.tr("Alarm") |
215 | onTriggered: { |
216 | if(isNewAlarm) { |
217 | @@ -182,6 +184,7 @@ |
218 | |
219 | SubtitledListItem { |
220 | id: _alarmRepeat |
221 | + objectName: "alarmRepeat" |
222 | |
223 | text: i18n.tr("Repeat") |
224 | subText: alarmUtils.format_day_string(_alarm.daysOfWeek) |
225 | @@ -191,6 +194,7 @@ |
226 | |
227 | SubtitledListItem { |
228 | id: _alarmLabel |
229 | + objectName: "alarmLabel" |
230 | |
231 | text: i18n.tr("Label") |
232 | subText: _alarm.message |
233 | @@ -200,6 +204,7 @@ |
234 | |
235 | SubtitledListItem { |
236 | id: _alarmSound |
237 | + objectName: "alarmSound" |
238 | /* |
239 | #TODO: Add support for choosing new alarm sound when indicator- |
240 | datetime supports custom alarm sounds |
241 | |
242 | === removed directory 'app/tests' |
243 | === removed directory 'app/tests/autopilot' |
244 | === removed file 'app/tests/autopilot/run' |
245 | --- app/tests/autopilot/run 2014-06-06 18:45:49 +0000 |
246 | +++ app/tests/autopilot/run 1970-01-01 00:00:00 +0000 |
247 | @@ -1,11 +0,0 @@ |
248 | -#!/bin/bash |
249 | - |
250 | -if [[ -z `which autopilot` ]]; then |
251 | - echo "Autopilot is not installed. Skip" |
252 | - exit |
253 | -fi |
254 | - |
255 | -SCRIPTPATH=`dirname $0` |
256 | -pushd ${SCRIPTPATH} |
257 | -autopilot run ubuntu-clock-app |
258 | -popd |
259 | |
260 | === removed directory 'app/tests/autopilot/ubuntu-clock-app' |
261 | === removed file 'app/tests/autopilot/ubuntu-clock-app/__init__.py' |
262 | --- app/tests/autopilot/ubuntu-clock-app/__init__.py 2014-06-06 18:45:49 +0000 |
263 | +++ app/tests/autopilot/ubuntu-clock-app/__init__.py 1970-01-01 00:00:00 +0000 |
264 | @@ -1,132 +0,0 @@ |
265 | -# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
266 | - |
267 | -"""Ubuntu Touch App autopilot tests.""" |
268 | - |
269 | -from os import remove |
270 | -import os.path |
271 | -from tempfile import mktemp |
272 | -import subprocess |
273 | - |
274 | -from autopilot.input import Mouse, Touch, Pointer |
275 | -from autopilot.matchers import Eventually |
276 | -from autopilot.platform import model |
277 | -from testtools.matchers import Is, Not, Equals |
278 | -from autopilot.testcase import AutopilotTestCase |
279 | - |
280 | -def get_module_include_path(): |
281 | - return os.path.abspath( |
282 | - os.path.join( |
283 | - os.path.dirname(__file__), |
284 | - '..', |
285 | - '..', |
286 | - '..', |
287 | - '..', |
288 | - 'backend', |
289 | - 'modules') |
290 | - ) |
291 | - |
292 | - |
293 | -class UbuntuTouchAppTestCase(AutopilotTestCase): |
294 | - """A common test case class that provides several useful methods for the tests.""" |
295 | - |
296 | - if model() == 'Desktop': |
297 | - scenarios = [ |
298 | - ('with mouse', dict(input_device_class=Mouse)) |
299 | - ] |
300 | - else: |
301 | - scenarios = [ |
302 | - ('with touch', dict(input_device_class=Touch)) |
303 | - ] |
304 | - |
305 | - @property |
306 | - def main_window(self): |
307 | - return MainWindow(self.app) |
308 | - |
309 | - |
310 | - def setUp(self): |
311 | - self.pointing_device = Pointer(self.input_device_class.create()) |
312 | - super(UbuntuTouchAppTestCase, self).setUp() |
313 | - self.launch_test_qml() |
314 | - |
315 | - |
316 | - def launch_test_qml(self): |
317 | - # If the test class has defined a 'test_qml' class attribute then we |
318 | - # write it to disk and launch it inside the QML Scene. If not, then we |
319 | - # silently do nothing (presumably the test has something else planned). |
320 | - arch = subprocess.check_output(["dpkg-architecture", |
321 | - "-qDEB_HOST_MULTIARCH"]).strip() |
322 | - if hasattr(self, 'test_qml') and isinstance(self.test_qml, basestring): |
323 | - qml_path = mktemp(suffix='.qml') |
324 | - open(qml_path, 'w').write(self.test_qml) |
325 | - self.addCleanup(remove, qml_path) |
326 | - |
327 | - self.app = self.launch_test_application( |
328 | - "/usr/lib/" + arch + "/qt5/bin/qmlscene", |
329 | - "-I", get_module_include_path(), |
330 | - qml_path, |
331 | - app_type='qt') |
332 | - |
333 | - if hasattr(self, 'test_qml_file') and isinstance(self.test_qml_file, basestring): |
334 | - qml_path = self.test_qml_file |
335 | - self.app = self.launch_test_application( |
336 | - "/usr/lib/" + arch + "/qt5/bin/qmlscene", |
337 | - "-I", get_module_include_path(), |
338 | - qml_path, |
339 | - app_type='qt') |
340 | - |
341 | - self.assertThat(self.get_qml_view().visible, Eventually(Equals(True))) |
342 | - |
343 | - |
344 | - def get_qml_view(self): |
345 | - """Get the main QML view""" |
346 | - |
347 | - return self.app.select_single("QQuickView") |
348 | - |
349 | - def get_mainview(self): |
350 | - """Get the QML MainView""" |
351 | - |
352 | - mainView = self.app.select_single("MainView") |
353 | - self.assertThat(mainView, Not(Is(None))) |
354 | - return mainView |
355 | - |
356 | - |
357 | - def get_object(self,objectName): |
358 | - """Get a object based on the objectName""" |
359 | - |
360 | - obj = self.app.select_single(objectName=objectName) |
361 | - self.assertThat(obj, Not(Is(None))) |
362 | - return obj |
363 | - |
364 | - |
365 | - def mouse_click(self,objectName): |
366 | - """Move mouse on top of the object and click on it""" |
367 | - |
368 | - obj = self.get_object(objectName) |
369 | - self.pointing_device.move_to_object(obj) |
370 | - self.pointing_device.click() |
371 | - |
372 | - |
373 | - def mouse_press(self,objectName): |
374 | - """Move mouse on top of the object and press mouse button (without releasing it)""" |
375 | - |
376 | - obj = self.get_object(objectName) |
377 | - self.pointing_device.move_to_object(obj) |
378 | - self.pointing_device.press() |
379 | - |
380 | - |
381 | - def mouse_release(self): |
382 | - """Release mouse button""" |
383 | - |
384 | - self.pointing_device.release() |
385 | - |
386 | - |
387 | - def type_string(self, string): |
388 | - """Type a string with keyboard""" |
389 | - |
390 | - self.keyboard.type(string) |
391 | - |
392 | - |
393 | - def type_key(self, key): |
394 | - """Type a single key with keyboard""" |
395 | - |
396 | - self.keyboard.key(key) |
397 | |
398 | === removed directory 'app/tests/autopilot/ubuntu-clock-app/main' |
399 | === removed file 'app/tests/autopilot/ubuntu-clock-app/main/__init__.py' |
400 | --- app/tests/autopilot/ubuntu-clock-app/main/__init__.py 2014-06-06 18:45:49 +0000 |
401 | +++ app/tests/autopilot/ubuntu-clock-app/main/__init__.py 1970-01-01 00:00:00 +0000 |
402 | @@ -1,1 +0,0 @@ |
403 | -""" A main.qml test suite """ |
404 | |
405 | === removed file 'app/tests/autopilot/ubuntu-clock-app/main/test_main.py' |
406 | --- app/tests/autopilot/ubuntu-clock-app/main/test_main.py 2014-06-06 18:45:49 +0000 |
407 | +++ app/tests/autopilot/ubuntu-clock-app/main/test_main.py 1970-01-01 00:00:00 +0000 |
408 | @@ -1,23 +0,0 @@ |
409 | -# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
410 | - |
411 | -"""Tests for the Hello World""" |
412 | - |
413 | -from autopilot.matchers import Eventually |
414 | -from textwrap import dedent |
415 | -from testtools.matchers import Is, Not, Equals |
416 | -from testtools import skip |
417 | -import os |
418 | -from ubuntu-clock-app import UbuntuTouchAppTestCase |
419 | - |
420 | - |
421 | -class MainTests(UbuntuTouchAppTestCase): |
422 | - """Generic tests for the Hello World""" |
423 | - |
424 | - test_qml_file = "%s/%s.qml" % (os.path.dirname(os.path.realpath(__file__)),"../../../../ubuntu-clock-app") |
425 | - |
426 | - def test_0_can_select_mainView(self): |
427 | - """Must be able to select the mainview.""" |
428 | - |
429 | - mainView = self.get_mainview() |
430 | - self.assertThat(mainView.visible,Eventually(Equals(True))) |
431 | - |
432 | |
433 | === removed directory 'app/tests/unit' |
434 | === removed file 'app/tests/unit/tst_hellocomponent.qml' |
435 | --- app/tests/unit/tst_hellocomponent.qml 2014-06-06 18:45:49 +0000 |
436 | +++ app/tests/unit/tst_hellocomponent.qml 1970-01-01 00:00:00 +0000 |
437 | @@ -1,49 +0,0 @@ |
438 | -import QtQuick 2.0 |
439 | -import QtTest 1.0 |
440 | -import Ubuntu.Components 0.1 |
441 | -import "../../components" |
442 | - |
443 | -// See more details @ http://qt-project.org/doc/qt-5.0/qtquick/qml-testcase.html |
444 | - |
445 | -// Execute tests with: |
446 | -// qmltestrunner |
447 | - |
448 | -Item { |
449 | - // The objects |
450 | - HelloComponent { |
451 | - id: objectUnderTest |
452 | - } |
453 | - |
454 | - TestCase { |
455 | - name: "HelloComponent" |
456 | - |
457 | - function init() { |
458 | - console.debug(">> init"); |
459 | - compare("",objectUnderTest.text,"text was not empty on init"); |
460 | - console.debug("<< init"); |
461 | - } |
462 | - |
463 | - function cleanup() { |
464 | - console.debug(">> cleanup"); |
465 | - console.debug("<< cleanup"); |
466 | - } |
467 | - |
468 | - function initTestCase() { |
469 | - console.debug(">> initTestCase"); |
470 | - console.debug("<< initTestCase"); |
471 | - } |
472 | - |
473 | - function cleanupTestCase() { |
474 | - console.debug(">> cleanupTestCase"); |
475 | - console.debug("<< cleanupTestCase"); |
476 | - } |
477 | - |
478 | - function test_canReadAndWriteText() { |
479 | - var expected = "Hello World"; |
480 | - |
481 | - objectUnderTest.text = expected; |
482 | - |
483 | - compare(expected,objectUnderTest.text,"expected did not equal result"); |
484 | - } |
485 | - } |
486 | -} |
487 | |
488 | === modified file 'manifest.json' |
489 | --- manifest.json 2014-07-08 10:52:02 +0000 |
490 | +++ manifest.json 2014-08-04 19:00:38 +0000 |
491 | @@ -11,5 +11,8 @@ |
492 | } |
493 | }, |
494 | "version": "0.1", |
495 | - "maintainer": "Ubuntu App Cats <ubuntu-touch-coreapps@lists.launchpad.net>" |
496 | -} |
497 | \ No newline at end of file |
498 | + "maintainer": "Ubuntu App Cats <ubuntu-touch-coreapps@lists.launchpad.net>", |
499 | + "x-test": { |
500 | + "autopilot": "ubuntu_clock_app" |
501 | + } |
502 | +} |
503 | |
504 | === added directory 'tests' |
505 | === added directory 'tests/autopilot' |
506 | === added file 'tests/autopilot/run' |
507 | --- tests/autopilot/run 1970-01-01 00:00:00 +0000 |
508 | +++ tests/autopilot/run 2014-08-04 19:00:38 +0000 |
509 | @@ -0,0 +1,11 @@ |
510 | +#!/bin/bash |
511 | + |
512 | +if [[ -z `which autopilot` ]]; then |
513 | + echo "Autopilot is not installed. Skip" |
514 | + exit |
515 | +fi |
516 | + |
517 | +SCRIPTPATH=`dirname $0` |
518 | +pushd ${SCRIPTPATH} |
519 | +autopilot run ubuntu-clock-app |
520 | +popd |
521 | |
522 | === added directory 'tests/autopilot/ubuntu_clock_app' |
523 | === added file 'tests/autopilot/ubuntu_clock_app/__init__.py' |
524 | --- tests/autopilot/ubuntu_clock_app/__init__.py 1970-01-01 00:00:00 +0000 |
525 | +++ tests/autopilot/ubuntu_clock_app/__init__.py 2014-08-04 19:00:38 +0000 |
526 | @@ -0,0 +1,18 @@ |
527 | +# Copyright (C) 2014 Canonical Ltd |
528 | +# |
529 | +# This file is part of Ubuntu Clock App |
530 | +# |
531 | +# Ubuntu Clock App is free software: you can redistribute it and/or modify |
532 | +# it under the terms of the GNU General Public License version 3 as |
533 | +# published by the Free Software Foundation. |
534 | +# |
535 | +# Ubuntu Clock App is distributed in the hope that it will be useful, |
536 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
537 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
538 | +# GNU General Public License for more details. |
539 | +# |
540 | +# You should have received a copy of the GNU General Public License |
541 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
542 | + |
543 | + |
544 | +"""clock-app autopilot tests and emulators - top level package.""" |
545 | |
546 | === added file 'tests/autopilot/ubuntu_clock_app/emulators.py' |
547 | --- tests/autopilot/ubuntu_clock_app/emulators.py 1970-01-01 00:00:00 +0000 |
548 | +++ tests/autopilot/ubuntu_clock_app/emulators.py 2014-08-04 19:00:38 +0000 |
549 | @@ -0,0 +1,395 @@ |
550 | +# Copyright (C) 2014 Canonical Ltd |
551 | +# |
552 | +# This file is part of Ubuntu Clock App |
553 | +# |
554 | +# Ubuntu Clock App is free software: you can redistribute it and/or modify |
555 | +# it under the terms of the GNU General Public License version 3 as |
556 | +# published by the Free Software Foundation. |
557 | +# |
558 | +# Ubuntu Clock App is distributed in the hope that it will be useful, |
559 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
560 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
561 | +# GNU General Public License for more details. |
562 | +# |
563 | +# You should have received a copy of the GNU General Public License |
564 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
565 | + |
566 | +import logging |
567 | + |
568 | +from autopilot import logging as autopilot_logging |
569 | + |
570 | +from ubuntuuitoolkit import pickers |
571 | +import ubuntuuitoolkit |
572 | + |
573 | +logger = logging.getLogger(__name__) |
574 | + |
575 | + |
576 | +class ClockEmulatorException(ubuntuuitoolkit.ToolkitException): |
577 | + |
578 | + """Exception raised when there is an error with the emulator.""" |
579 | + |
580 | + |
581 | +class MainView(ubuntuuitoolkit.MainView): |
582 | + |
583 | + @autopilot_logging.log_action(logger.info) |
584 | + def open_clock(self): |
585 | + """Open the Clock Page. |
586 | + |
587 | + :return the Clock Page |
588 | + |
589 | + """ |
590 | + return self.wait_select_single(ClockPage) |
591 | + |
592 | + @autopilot_logging.log_action(logger.info) |
593 | + def open_alarm(self): |
594 | + """Open the Alarm Page. |
595 | + |
596 | + :return: the Alarm Page. |
597 | + |
598 | + """ |
599 | + clockPage = self.wait_select_single(ClockPage) |
600 | + clockPage.drag_bottomEdge_up() |
601 | + self.get_header().visible.wait_for(True) |
602 | + return self.wait_select_single(Page11) |
603 | + |
604 | + def get_AlarmList(self): |
605 | + """ Get the AlarmList object. """ |
606 | + return AlarmList.select(self) |
607 | + |
608 | + |
609 | +class Page(ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase): |
610 | + |
611 | + """Autopilot helper for Pages.""" |
612 | + |
613 | + def __init__(self, *args): |
614 | + super(Page, self).__init__(*args) |
615 | + # XXX we need a better way to keep reference to the main view. |
616 | + # --elopio - 2014-01-31 |
617 | + self.main_view = self.get_root_instance().select_single(MainView) |
618 | + |
619 | + |
620 | +class ClockPage(Page): |
621 | + |
622 | + """Autopilot helper for the Clock page.""" |
623 | + |
624 | + @autopilot_logging.log_action(logger.info) |
625 | + def drag_bottomEdge_up(self): |
626 | + """Function to drag the bottom edge up.""" |
627 | + self._click_bottomEdge() |
628 | + |
629 | + x, y, w, h = self.globalRect |
630 | + start_x = stop_x = x + (w / 2) |
631 | + start_y = y + (h - 1) |
632 | + |
633 | + stop_y = start_y - h |
634 | + self.pointing_device.drag(start_x, start_y, stop_x, stop_y) |
635 | + |
636 | + self._wait_for_ClockPage_to_close() |
637 | + |
638 | + def _click_bottomEdge(self): |
639 | + """Function to click on the bottom edge.""" |
640 | + bottomEdge = self.wait_select_single( |
641 | + 'QQuickItem', objectName='bottomEdgeTip') |
642 | + self.pointing_device.click_object(bottomEdge) |
643 | + |
644 | + def _wait_for_ClockPage_to_close(self): |
645 | + self.isCollapsed.wait_for(False) |
646 | + |
647 | + |
648 | +class Page11(Page): |
649 | + |
650 | + """Autopilot helper for the Alarm page.""" |
651 | + |
652 | + @autopilot_logging.log_action(logger.info) |
653 | + def add_single_alarm(self, name, day, time_to_set, test_sound_name): |
654 | + """Add a single type alarm |
655 | + |
656 | + :param name: name of alarm |
657 | + :param day: day on which the alarm should be triggered |
658 | + :param time_to_set: time to set alarm to |
659 | + :param test_sound_name: sound to set in alarm |
660 | + |
661 | + """ |
662 | + alarmListPage = AlarmList.select(self.main_view) |
663 | + old_alarm_count = alarmListPage.get_num_of_alarms() |
664 | + |
665 | + edit_alarm_page = self._click_add_alarm_button() |
666 | + edit_alarm_page.set_alarm_time(time_to_set) |
667 | + |
668 | + alarm_repeat_page = edit_alarm_page.open_alarmRepeat_page() |
669 | + alarm_repeat_page.set_single_alarm_day(day) |
670 | + self._click_header_backButton() |
671 | + |
672 | + alarm_label_page = edit_alarm_page.open_alarmLabel_page() |
673 | + alarm_label_page.set_alarm_label(name) |
674 | + self._click_header_customBackButton() |
675 | + |
676 | + alarm_sound_page = edit_alarm_page.open_alarmSound_page() |
677 | + alarm_sound_page.set_alarm_sound(test_sound_name) |
678 | + self._click_header_customBackButton() |
679 | + edit_alarm_page._check_sound_changed(test_sound_name) |
680 | + |
681 | + self._click_save() |
682 | + self._confirm_alarm_creation(old_alarm_count) |
683 | + |
684 | + def _click_add_alarm_button(self): |
685 | + """Click the add alarm header button.""" |
686 | + header = self.main_view.get_header() |
687 | + header.click_action_button('addAlarmAction') |
688 | + return self.main_view.wait_select_single(EditAlarmPage) |
689 | + |
690 | + def _click_header_customBackButton(self): |
691 | + """Click the header button: 'customBackButton' """ |
692 | + header = self.main_view.get_header() |
693 | + header.click_custom_back_button() |
694 | + |
695 | + def _click_header_backButton(self): |
696 | + """Click the header button: 'backButton' """ |
697 | + header = self.main_view.get_header() |
698 | + header.click_back_button() |
699 | + |
700 | + def _click_save(self): |
701 | + """Click the save timer header button""" |
702 | + header = self.main_view.get_header() |
703 | + header.click_action_button('saveAlarmAction') |
704 | + |
705 | + def _confirm_alarm_creation(self, count): |
706 | + """Confirm creation of alarm |
707 | + |
708 | + :param count: alarm count before alarm creation |
709 | + |
710 | + """ |
711 | + try: |
712 | + AlarmList.select(self.main_view)._get_saved_alarms_list().\ |
713 | + count.wait_for(count + 1) |
714 | + except AssertionError: |
715 | + raise ClockEmulatorException('Error creating alarm.') |
716 | + |
717 | + |
718 | +class EditAlarmPage(Page): |
719 | + |
720 | + """Autopilot helper for the Add Alarm page.""" |
721 | + |
722 | + @autopilot_logging.log_action(logger.info) |
723 | + def set_alarm_time(self, time_to_set): |
724 | + """Set alarm time on datepicker. |
725 | + |
726 | + :param time_to_set: time to set on datepicker |
727 | + |
728 | + """ |
729 | + PickerRow_HoursPicker = self.wait_select_single( |
730 | + "Picker", objectName="PickerRow_HoursPicker") |
731 | + self._set_picker(PickerRow_HoursPicker, 'time', time_to_set) |
732 | + |
733 | + def _set_picker(self, field, mode, value): |
734 | + # open picker |
735 | + self.pointing_device.click_object(field) |
736 | + # valid options are date or time; assume date if invalid/no option |
737 | + mode_value = 'Hours|Minutes' |
738 | + picker = self.wait_select_single( |
739 | + pickers.DatePicker, mode=mode_value, visible=True) |
740 | + picker.pick_time(value) |
741 | + # close picker |
742 | + self.pointing_device.click_object(field) |
743 | + |
744 | + @autopilot_logging.log_action(logger.info) |
745 | + def open_alarmRepeat_page(self): |
746 | + """ Open the alarmRepeat page """ |
747 | + |
748 | + alarmRepeatItem = self.wait_select_single( |
749 | + "SubtitledListItem", objectName="alarmRepeat") |
750 | + self.pointing_device.click_object(alarmRepeatItem) |
751 | + return self.main_view.wait_select_single(AlarmRepeat) |
752 | + |
753 | + @autopilot_logging.log_action(logger.info) |
754 | + def open_alarmLabel_page(self): |
755 | + """ Open the alarmLabel page """ |
756 | + |
757 | + alarmLabelItem = self.wait_select_single( |
758 | + "SubtitledListItem", objectName="alarmLabel") |
759 | + self.pointing_device.click_object(alarmLabelItem) |
760 | + return AlarmLable.select(self.main_view) |
761 | + |
762 | + @autopilot_logging.log_action(logger.info) |
763 | + def open_alarmSound_page(self): |
764 | + """ Open the alarmSound page """ |
765 | + |
766 | + alarmSoundItem = self.wait_select_single( |
767 | + "SubtitledListItem", objectName="alarmSound") |
768 | + self.pointing_device.click_object(alarmSoundItem) |
769 | + return self.main_view.wait_select_single(AlarmSound) |
770 | + |
771 | + def _check_sound_changed(self, test_sound_name): |
772 | + """ function to check that sound has changed. |
773 | + |
774 | + :param test_sound_name = new sound name |
775 | + |
776 | + """ |
777 | + self.wait_select_single("SubtitledListItem", objectName="alarmSound")\ |
778 | + .subText == test_sound_name |
779 | + |
780 | + |
781 | +class AlarmRepeat(Page): |
782 | + |
783 | + """Autopilot helper for the AlarmRepeat page.""" |
784 | + |
785 | + @autopilot_logging.log_action(logger.info) |
786 | + def set_single_alarm_day(self, day): |
787 | + """Set the alarm day of a single type alarm. |
788 | + |
789 | + :param day: single day on which alarm is triggered |
790 | + |
791 | + """ |
792 | + self.unselect_selected_days() |
793 | + index = 0 |
794 | + for index in range(self._get_num_of_days()): |
795 | + if self.wait_select_single( |
796 | + 'Label', objectName='alarmDay{}'.format(index))\ |
797 | + .text == day: |
798 | + self._select_single_alarm_day(index) |
799 | + break |
800 | + |
801 | + def _get_num_of_days(self): |
802 | + return int(self.wait_select_single( |
803 | + 'QQuickRepeater', objectName='alarmDays').count) |
804 | + |
805 | + def _select_single_alarm_day(self, index): |
806 | + """ function for selecting the day passed to the function. |
807 | + |
808 | + :param index: the day to be selected |
809 | + |
810 | + """ |
811 | + dayCheckbox = self.wait_select_single( |
812 | + 'CheckBox', objectName='daySwitch{}'.format(index)) |
813 | + dayCheckbox.check() |
814 | + |
815 | + @autopilot_logging.log_action(logger.info) |
816 | + def unselect_selected_days(self): |
817 | + """ function for unselecting already selected days. """ |
818 | + for index in range(self._get_num_of_days()): |
819 | + dayCheckbox = self.wait_select_single( |
820 | + 'CheckBox', objectName='daySwitch{}'.format(index)) |
821 | + dayCheckbox.uncheck() |
822 | + |
823 | + |
824 | +class AlarmSound(Page): |
825 | + |
826 | + """Autopilot helper for the AlarmSound page.""" |
827 | + |
828 | + @autopilot_logging.log_action(logger.info) |
829 | + def set_alarm_sound(self, test_sound_name): |
830 | + """Set alarm sound. |
831 | + |
832 | + :param test_sound_name: sound to set for alarm |
833 | + |
834 | + """ |
835 | + for index in range(self._get_num_of_sounds()): |
836 | + if self.wait_select_single( |
837 | + 'Label', objectName='soundName{}'.format(index)).\ |
838 | + text == test_sound_name: |
839 | + self._select_alarm_sound(index) |
840 | + break |
841 | + |
842 | + def _get_num_of_sounds(self): |
843 | + return int(self.wait_select_single( |
844 | + 'QQuickRepeater', objectName='alarmSounds').count) |
845 | + |
846 | + def _select_alarm_sound(self, index): |
847 | + """ function for selecting the sound passed to the function. |
848 | + |
849 | + :param index: the sound to be selected |
850 | + |
851 | + """ |
852 | + soundCheckbox = self.wait_select_single( |
853 | + 'CheckBox', objectName='soundStatus{}'.format(index)) |
854 | + soundCheckbox.check() |
855 | + |
856 | + |
857 | +class AlarmLable(object): |
858 | + |
859 | + """Autopilot helper for the AlarmLabel page.""" |
860 | + |
861 | + def __init__(self, proxy_object): |
862 | + super(AlarmLable, self).__init__() |
863 | + self.proxy_object = proxy_object |
864 | + |
865 | + @classmethod |
866 | + def select(cls, main_view): |
867 | + proxy_object = main_view.wait_select_single( |
868 | + objectName='alarmLabelPage') |
869 | + proxy_object.visible.wait_for(True) |
870 | + return cls(proxy_object) |
871 | + |
872 | + @autopilot_logging.log_action(logger.info) |
873 | + def set_alarm_label(self, name): |
874 | + """Set alarm label. |
875 | + |
876 | + :param name: label for alarm to set |
877 | + |
878 | + """ |
879 | + alarmTextfield = self.proxy_object.wait_select_single( |
880 | + "TextField", objectName='labelEntry') |
881 | + # TODO: This wait to ensure that the textfield is visible before |
882 | + # entering text should be part of the SDK emulator. Until then, it has |
883 | + # been added here. http://pad.lv/1289616 --nik90 2014-03-06 |
884 | + alarmTextfield.visible.wait_for(True) |
885 | + alarmTextfield.write(name) |
886 | + |
887 | + |
888 | +class AlarmList(object): |
889 | + |
890 | + """Autopilot helper for the AlarmList.""" |
891 | + |
892 | + def __init__(self, proxy_object): |
893 | + super(AlarmList, self).__init__() |
894 | + self.proxy_object = proxy_object |
895 | + |
896 | + @classmethod |
897 | + def select(cls, main_view): |
898 | + proxy_object = main_view.wait_select_single( |
899 | + objectName='alarmListFlickable') |
900 | + proxy_object.visible.wait_for(True) |
901 | + return cls(proxy_object) |
902 | + |
903 | + def get_num_of_alarms(self): |
904 | + """Return the number of saved alarms.""" |
905 | + return int(self._get_saved_alarms_list().count) |
906 | + |
907 | + def _get_saved_alarms_list(self): |
908 | + """Return the saved alarm list""" |
909 | + return self.proxy_object.wait_select_single( |
910 | + 'QQuickRepeater', objectName='alarmListRepeater') |
911 | + |
912 | + def get_saved_alarms(self): |
913 | + """Return a list with the information of the saved alarms. |
914 | + |
915 | + Each item of the returned list is a tuple of |
916 | + (name, recurrence, time, enabled). |
917 | + |
918 | + """ |
919 | + alarms = [] |
920 | + for index in range(self.get_num_of_alarms()): |
921 | + name = self.proxy_object.wait_select_single( |
922 | + 'Label', objectName='listAlarmLabel{}'.format(index)).text |
923 | + recurrence = self.proxy_object.wait_select_single( |
924 | + 'Label', objectName='listAlarmSubtitle{}'.format(index)).text |
925 | + time = self.proxy_object.wait_select_single( |
926 | + 'Label', objectName='listAlarmTime{}'.format(index)).text |
927 | + enabled = self.proxy_object.wait_select_single( |
928 | + ubuntuuitoolkit.CheckBox, |
929 | + objectName='listAlarmStatus{}'.format(index)).checked |
930 | + alarms.append((name, recurrence, enabled, time)) |
931 | + return alarms |
932 | + |
933 | + @autopilot_logging.log_action(logger.info) |
934 | + def delete_alarm(self, index): |
935 | + """Delete an alarm at the specified index.""" |
936 | + old_alarm_count = self.get_num_of_alarms() |
937 | + alarm = self.proxy_object.wait_select_single( |
938 | + 'Base', objectName='alarm{}'.format(index)) |
939 | + alarm.swipe_to_delete() |
940 | + alarm.confirm_removal() |
941 | + try: |
942 | + self._get_saved_alarms_list().count.wait_for(old_alarm_count - 1) |
943 | + except AssertionError: |
944 | + raise ClockEmulatorException('Error deleting alarm.') |
945 | |
946 | === added directory 'tests/autopilot/ubuntu_clock_app/tests' |
947 | === added file 'tests/autopilot/ubuntu_clock_app/tests/__init__.py' |
948 | --- tests/autopilot/ubuntu_clock_app/tests/__init__.py 1970-01-01 00:00:00 +0000 |
949 | +++ tests/autopilot/ubuntu_clock_app/tests/__init__.py 2014-08-04 19:00:38 +0000 |
950 | @@ -0,0 +1,125 @@ |
951 | +# Copyright (C) 2014 Canonical Ltd |
952 | +# |
953 | +# This file is part of Ubuntu Clock App |
954 | +# |
955 | +# Ubuntu Clock App is free software: you can redistribute it and/or modify |
956 | +# it under the terms of the GNU General Public License version 3 as |
957 | +# published by the Free Software Foundation. |
958 | +# |
959 | +# Ubuntu Clock App is distributed in the hope that it will be useful, |
960 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
961 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
962 | +# GNU General Public License for more details. |
963 | +# |
964 | +# You should have received a copy of the GNU General Public License |
965 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
966 | + |
967 | +"""clock-app autopilot tests.""" |
968 | + |
969 | +import os.path |
970 | +import os |
971 | +import shutil |
972 | +import logging |
973 | +import fixtures |
974 | + |
975 | +from autopilot import input |
976 | +from autopilot.platform import model |
977 | +from ubuntuuitoolkit import ( |
978 | + base, |
979 | + emulators as toolkit_emulators |
980 | +) |
981 | + |
982 | +from ubuntu_clock_app import emulators |
983 | + |
984 | +logger = logging.getLogger(__name__) |
985 | + |
986 | + |
987 | +class ClockAppTestCase(base.UbuntuUIToolkitAppTestCase): |
988 | + |
989 | + """A common test case class that provides several useful methods for |
990 | + clock-app tests. |
991 | + |
992 | + """ |
993 | + local_location = "../../app/ubuntu-clock-app.qml" |
994 | + local_backend_dir = "../../builddir/backend/" |
995 | + installed_location = "/usr/share/ubuntu-clock-app/app/ubuntu-clock-app.qml" |
996 | + installed_backend_dir = "/usr/share/ubuntu-clock-app/builddir/backend/" |
997 | + sqlite_dir = os.path.expanduser( |
998 | + "~/.local/share/com.ubuntu.clock") |
999 | + backup_dir = sqlite_dir + ".backup" |
1000 | + |
1001 | + def setUp(self): |
1002 | + super(ClockAppTestCase, self).setUp() |
1003 | + self.pointing_device = input.Pointer(self.input_device_class.create()) |
1004 | + |
1005 | + self.useFixture(fixtures.EnvironmentVariable('LC_ALL', newvalue='C')) |
1006 | + |
1007 | + # backup and wipe db's before testing |
1008 | + self.temp_move_sqlite_db() |
1009 | + self.addCleanup(self.restore_sqlite_db) |
1010 | + |
1011 | + # turn off the OSK so it doesn't block screen elements |
1012 | + if model() != 'Desktop': |
1013 | + os.system("stop maliit-server") |
1014 | + self.addCleanup(os.system, "start maliit-server") |
1015 | + |
1016 | + if os.path.exists(self.local_location): |
1017 | + self.launch_test_local() |
1018 | + elif os.path.exists(self.installed_location): |
1019 | + self.launch_test_installed() |
1020 | + else: |
1021 | + self.launch_test_click() |
1022 | + |
1023 | + def launch_test_local(self): |
1024 | + self.app = self.launch_test_application( |
1025 | + base.get_qmlscene_launch_command(), |
1026 | + self.local_location, |
1027 | + "-I", self.local_backend_dir, |
1028 | + app_type='qt', |
1029 | + emulator_base=toolkit_emulators.UbuntuUIToolkitEmulatorBase) |
1030 | + |
1031 | + def launch_test_installed(self): |
1032 | + self.app = self.launch_test_application( |
1033 | + base.get_qmlscene_launch_command(), |
1034 | + self.installed_location, |
1035 | + "-I", self.installed_backend_dir, |
1036 | + app_type='qt', |
1037 | + emulator_base=toolkit_emulators.UbuntuUIToolkitEmulatorBase) |
1038 | + |
1039 | + def launch_test_click(self): |
1040 | + self.app = self.launch_click_package( |
1041 | + "com.ubuntu.clock.devel", |
1042 | + emulator_base=toolkit_emulators.UbuntuUIToolkitEmulatorBase) |
1043 | + |
1044 | + def temp_move_sqlite_db(self): |
1045 | + try: |
1046 | + shutil.rmtree(self.backup_dir) |
1047 | + except: |
1048 | + pass |
1049 | + else: |
1050 | + logger.warning("Prexisting backup database found and removed") |
1051 | + |
1052 | + try: |
1053 | + shutil.move(self.sqlite_dir, self.backup_dir) |
1054 | + except: |
1055 | + logger.warning("No current database found") |
1056 | + else: |
1057 | + logger.debug("Backed up database") |
1058 | + |
1059 | + def restore_sqlite_db(self): |
1060 | + if os.path.exists(self.backup_dir): |
1061 | + if os.path.exists(self.sqlite_dir): |
1062 | + try: |
1063 | + shutil.rmtree(self.sqlite_dir) |
1064 | + except: |
1065 | + logger.error("Failed to remove test database and restore" / |
1066 | + "database") |
1067 | + return |
1068 | + try: |
1069 | + shutil.move(self.backup_dir, self.sqlite_dir) |
1070 | + except: |
1071 | + logger.error("Failed to restore database") |
1072 | + |
1073 | + @property |
1074 | + def main_view(self): |
1075 | + return self.app.wait_select_single(emulators.MainView) |
1076 | |
1077 | === added file 'tests/autopilot/ubuntu_clock_app/tests/test_alarm.py' |
1078 | --- tests/autopilot/ubuntu_clock_app/tests/test_alarm.py 1970-01-01 00:00:00 +0000 |
1079 | +++ tests/autopilot/ubuntu_clock_app/tests/test_alarm.py 2014-08-04 19:00:38 +0000 |
1080 | @@ -0,0 +1,84 @@ |
1081 | +# Copyright (C) 2014 Canonical Ltd |
1082 | +# |
1083 | +# This file is part of Ubuntu Clock App |
1084 | +# |
1085 | +# Ubuntu Clock App is free software: you can redistribute it and/or modify |
1086 | +# it under the terms of the GNU General Public License version 3 as |
1087 | +# published by the Free Software Foundation. |
1088 | +# |
1089 | +# Ubuntu Clock App is distributed in the hope that it will be useful, |
1090 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1091 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1092 | +# GNU General Public License for more details. |
1093 | +# |
1094 | +# You should have received a copy of the GNU General Public License |
1095 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1096 | + |
1097 | +"""Tests for the Clock App - Alarm""" |
1098 | + |
1099 | +from __future__ import absolute_import |
1100 | + |
1101 | +import datetime |
1102 | +import unittest |
1103 | + |
1104 | +from autopilot.matchers import Eventually |
1105 | +from testtools.matchers import Equals |
1106 | +from ubuntu_clock_app.tests import ClockAppTestCase |
1107 | +from autopilot.platform import model |
1108 | + |
1109 | + |
1110 | +class TestAlarm(ClockAppTestCase): |
1111 | + |
1112 | + """Tests the alarm page features""" |
1113 | + |
1114 | + def setUp(self): |
1115 | + """ This is needed to wait for the application to start. |
1116 | + |
1117 | + In the testfarm, the application may take some time to show up. |
1118 | + |
1119 | + """ |
1120 | + super(TestAlarm, self).setUp() |
1121 | + self.assertThat( |
1122 | + self.main_view.visible, Eventually(Equals(True))) |
1123 | + |
1124 | + self.page = self.main_view.open_alarm() |
1125 | + |
1126 | + # TODO |
1127 | + # Due to bug https://bugs.launchpad.net/ubuntu-calendar-app/+bug/1328600 |
1128 | + # this test cannot be run on device, so until the bug is not fixed we are |
1129 | + # skipping the test if model not Desktop. |
1130 | + @unittest.skipIf(model() != 'Desktop', |
1131 | + "datepicker does not work correctly on device") |
1132 | + def test_add_recurring_type_alarm_must_add_to_alarm_list(self): |
1133 | + """Test to check if a single type alarm is saved properly |
1134 | + |
1135 | + This test saves a single type alarm and verifies if it is added to the |
1136 | + alarm list in the alarm page. |
1137 | + |
1138 | + """ |
1139 | + tomorrow = datetime.datetime.now() + datetime.timedelta(days=1) |
1140 | + time_to_set = datetime.time(6, 10, 0) |
1141 | + test_alarm_name = 'Single Test' |
1142 | + # TODO this will be affected by the locale. --elopio - 2014-02-27 |
1143 | + expected_alarm_name = test_alarm_name |
1144 | + expected_recurrence = tomorrow.strftime('%A') |
1145 | + expected_enabled_value = True |
1146 | + expected_time = "06:10:00" |
1147 | + test_sound_name = "Bliss" |
1148 | + expected_alarm_info = ( |
1149 | + expected_alarm_name, expected_recurrence, expected_enabled_value, |
1150 | + expected_time) |
1151 | + |
1152 | + tomorrow_day = tomorrow.strftime('%A') |
1153 | + self.page.add_single_alarm( |
1154 | + test_alarm_name, tomorrow_day, time_to_set, test_sound_name) |
1155 | + |
1156 | + alarmlistPage = self.main_view.get_AlarmList() |
1157 | + saved_alarms = alarmlistPage.get_saved_alarms() |
1158 | + self.assertIn(expected_alarm_info, saved_alarms) |
1159 | + |
1160 | + # TODO: Remove this statement once proper support for cleaning the |
1161 | + # test alarm environment is added. Until then remove the alarm |
1162 | + # created during the test at the end of the test. |
1163 | + # -- nik90 - 2014-03-03 |
1164 | + alarmlistPage.delete_alarm(index=0) |
1165 | |
1166 | === added file 'tests/autopilot/ubuntu_clock_app/tests/test_clock.py' |
1167 | --- tests/autopilot/ubuntu_clock_app/tests/test_clock.py 1970-01-01 00:00:00 +0000 |
1168 | +++ tests/autopilot/ubuntu_clock_app/tests/test_clock.py 2014-08-04 19:00:38 +0000 |
1169 | @@ -0,0 +1,44 @@ |
1170 | +# Copyright (C) 2014 Canonical Ltd |
1171 | +# |
1172 | +# This file is part of Ubuntu Clock App |
1173 | +# |
1174 | +# Ubuntu Clock App is free software: you can redistribute it and/or modify |
1175 | +# it under the terms of the GNU General Public License version 3 as |
1176 | +# published by the Free Software Foundation. |
1177 | +# |
1178 | +# Ubuntu Clock App is distributed in the hope that it will be useful, |
1179 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1180 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1181 | +# GNU General Public License for more details. |
1182 | +# |
1183 | +# You should have received a copy of the GNU General Public License |
1184 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1185 | + |
1186 | +""" |
1187 | +Tests for the Clock App, main window. |
1188 | +""" |
1189 | + |
1190 | +from __future__ import absolute_import |
1191 | + |
1192 | +from testtools.matchers import Equals |
1193 | +from autopilot.matchers import Eventually |
1194 | + |
1195 | +from ubuntu_clock_app.tests import ClockAppTestCase |
1196 | + |
1197 | + |
1198 | +class TestClock(ClockAppTestCase): |
1199 | + |
1200 | + """Test the clock page features.""" |
1201 | + |
1202 | + def setUp(self): |
1203 | + """This is needed to wait for the application to start. |
1204 | + |
1205 | + In the testfarm, the application may take some time to show up. |
1206 | + |
1207 | + """ |
1208 | + |
1209 | + super(TestClock, self).setUp() |
1210 | + self.assertThat( |
1211 | + self.main_view.visible, Eventually(Equals(True))) |
1212 | + |
1213 | + self.page = self.main_view.open_clock() |
1214 | |
1215 | === added directory 'tests/unit' |
1216 | === added file 'tests/unit/tst_hellocomponent.qml' |
1217 | --- tests/unit/tst_hellocomponent.qml 1970-01-01 00:00:00 +0000 |
1218 | +++ tests/unit/tst_hellocomponent.qml 2014-08-04 19:00:38 +0000 |
1219 | @@ -0,0 +1,49 @@ |
1220 | +import QtQuick 2.0 |
1221 | +import QtTest 1.0 |
1222 | +import Ubuntu.Components 0.1 |
1223 | +import "../../components" |
1224 | + |
1225 | +// See more details @ http://qt-project.org/doc/qt-5.0/qtquick/qml-testcase.html |
1226 | + |
1227 | +// Execute tests with: |
1228 | +// qmltestrunner |
1229 | + |
1230 | +Item { |
1231 | + // The objects |
1232 | + HelloComponent { |
1233 | + id: objectUnderTest |
1234 | + } |
1235 | + |
1236 | + TestCase { |
1237 | + name: "HelloComponent" |
1238 | + |
1239 | + function init() { |
1240 | + console.debug(">> init"); |
1241 | + compare("",objectUnderTest.text,"text was not empty on init"); |
1242 | + console.debug("<< init"); |
1243 | + } |
1244 | + |
1245 | + function cleanup() { |
1246 | + console.debug(">> cleanup"); |
1247 | + console.debug("<< cleanup"); |
1248 | + } |
1249 | + |
1250 | + function initTestCase() { |
1251 | + console.debug(">> initTestCase"); |
1252 | + console.debug("<< initTestCase"); |
1253 | + } |
1254 | + |
1255 | + function cleanupTestCase() { |
1256 | + console.debug(">> cleanupTestCase"); |
1257 | + console.debug("<< cleanupTestCase"); |
1258 | + } |
1259 | + |
1260 | + function test_canReadAndWriteText() { |
1261 | + var expected = "Hello World"; |
1262 | + |
1263 | + objectUnderTest.text = expected; |
1264 | + |
1265 | + compare(expected,objectUnderTest.text,"expected did not equal result"); |
1266 | + } |
1267 | + } |
1268 | +} |
I am having a UnicodeDecodeError and not sure how to handle it.