Merge lp:~elopio/ubuntu-clock-app/refactor_timer_tests into lp:ubuntu-clock-app/saucy
- refactor_timer_tests
- Merge into saucy
Status: | Merged |
---|---|
Approved by: | Nekhelesh Ramananthan |
Approved revision: | 337 |
Merged at revision: | 350 |
Proposed branch: | lp:~elopio/ubuntu-clock-app/refactor_timer_tests |
Merge into: | lp:ubuntu-clock-app/saucy |
Diff against target: |
602 lines (+249/-160) 7 files modified
alarm/AddAlarmPage.qml (+1/-0) alarm/AlarmPage.qml (+1/-0) stopwatch/StopwatchPage.qml (+1/-0) tests/autopilot/ubuntu_clock_app/emulators.py (+193/-46) tests/autopilot/ubuntu_clock_app/tests/test_clock.py (+1/-0) tests/autopilot/ubuntu_clock_app/tests/test_timer.py (+43/-106) timer/PresetList.qml (+9/-8) |
To merge this branch: | bzr merge lp:~elopio/ubuntu-clock-app/refactor_timer_tests |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu Phone Apps Jenkins Bot | continuous-integration | Approve | |
Nekhelesh Ramananthan | Approve | ||
Nicholas Skaggs (community) | Approve | ||
Review via email: mp+207307@code.launchpad.net |
This proposal supersedes a proposal from 2014-01-31.
Commit message
Refactored the timer autopilot tests.
Description of the change
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal | # |
Leo Arias (elopio) wrote : Posted in a previous version of this proposal | # |
I fixed pep8 and pyflakes, because I'm a freak and can't live without that.
Then, I encapsulated the actions of the timer page in the TimerPage class, making public only the methods that represent action users. All internal things, like _get_X_element, or _click_something are private details of the emulators.
With this we make sure that the tests are high level user stories. They are short, and use the user language.
Lets say that in the future, designers decide that it's best if we add a button to add timers instead of doing that from the toolbar. In that case, we don't have to modify the test case, we only have to modify the _click_
On the prerequisite branch, nik added a check that the name of the timer was properly written. I moved it to
260 + if name_label.text != name:
but, the right thing to do is to have the textfield emulator making the check for us. I reported that as bug https:/
Nicholas Skaggs (nskaggs) wrote : Posted in a previous version of this proposal | # |
So most of this is actually pep8 and pyflakes. Don't worry Leo, it bothers me as well (even though I don't like pep8 in some cases).
Most of the restructuring is straightforward; really nothing crazy. It gets my +1. I will say, it's difficult to read the diff because of the pep8 and pyflakes changes, but I understand the desire to lump them.
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:318
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:318
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:318
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:320
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:320
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:321
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:322
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Nicholas Skaggs (nskaggs) wrote : | # |
I had started on this at one point; glad you've seen it through :-)
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:323
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:323
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
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://
FAILURE: http://
FAILURE: http://
Nekhelesh Ramananthan (nik90) wrote : | # |
I think you will need to another massive trunk merge since we just landed the convergence layout design into trunk few minutes ago. This means that the test will need to adapt if it is running the phone or tablet interface. I have already accounted for this in trunk. You will need to merge trunk to get those important AP fixes.
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:325
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Nekhelesh Ramananthan (nik90) wrote : | # |
547 - // TODO: Fix autopilot test first before enabling this change in another MP
548 - //PropertyChanges { target: namePreset; text: "Timer #" + (listPreset.
549 + PropertyChanges { target: namePreset; text: "Timer #" + (listPreset.
This fix is not present in the trunk. I believe this is an old remaining part from the add-timer-
189 + self.drag_page_up()
I see this code in several places. It won't work for the following reasons,
a) You need a condition to check if dragging the page action is necessary in the first place since in the tablet interface there is dragging page up/down actions. This is why I added the if condition, if not(self.
Nekhelesh Ramananthan (nik90) wrote : | # |
In my comment above I meant that there are *no* dragging the page up/down actions.
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:327
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:328
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:328
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:329
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:330
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:330
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:331
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:332
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:333
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:334
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:335
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Nekhelesh Ramananthan (nik90) wrote : | # |
Wow! Well organised and look awesome. It just needs two small fixes.
521 + self.page.
534 + self.page.
In these two lines in test_timer.py you can the function drag_page_up() without checking if the interface is phone or tablet. As a result when I tested on my desktop using tablet interface, AP tried dragging the page up, however there was nothing to drag up. The test did still pass, but it would be nice to check the interface before doing this step.
A if loop like below should fix it.
if not self.main_
+ self.drag_page_up()
Otherwise this commit is ready for merge.
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) : | # |
Preview Diff
1 | === modified file 'alarm/AddAlarmPage.qml' |
2 | --- alarm/AddAlarmPage.qml 2014-02-19 17:43:14 +0000 |
3 | +++ alarm/AddAlarmPage.qml 2014-02-24 16:24:49 +0000 |
4 | @@ -324,6 +324,7 @@ |
5 | |
6 | Flickable { |
7 | id: addAlarmPageAnimationContainer |
8 | + objectName: "animationContainer" |
9 | |
10 | anchors.fill: parent |
11 | contentWidth: addAlarmPage.width |
12 | |
13 | === modified file 'alarm/AlarmPage.qml' |
14 | --- alarm/AlarmPage.qml 2014-02-19 17:43:14 +0000 |
15 | +++ alarm/AlarmPage.qml 2014-02-24 16:24:49 +0000 |
16 | @@ -199,6 +199,7 @@ |
17 | |
18 | Flickable { |
19 | id: alarmAnimationContainer |
20 | + objectName: "animationContainer" |
21 | |
22 | Component.onCompleted: alarmPageFlickable = alarmAnimationContainer |
23 | |
24 | |
25 | === modified file 'stopwatch/StopwatchPage.qml' |
26 | --- stopwatch/StopwatchPage.qml 2014-02-19 17:43:14 +0000 |
27 | +++ stopwatch/StopwatchPage.qml 2014-02-24 16:24:49 +0000 |
28 | @@ -197,6 +197,7 @@ |
29 | |
30 | Flickable { |
31 | id: stopwatchAnimationContainer |
32 | + objectName: "animationContainer" |
33 | |
34 | Component.onCompleted: stopwatchPageFlickable = stopwatchAnimationContainer |
35 | |
36 | |
37 | === modified file 'tests/autopilot/ubuntu_clock_app/emulators.py' |
38 | --- tests/autopilot/ubuntu_clock_app/emulators.py 2014-02-19 18:04:36 +0000 |
39 | +++ tests/autopilot/ubuntu_clock_app/emulators.py 2014-02-24 16:24:49 +0000 |
40 | @@ -21,8 +21,11 @@ |
41 | from time import sleep |
42 | |
43 | from autopilot import logging as autopilot_logging |
44 | + |
45 | + |
46 | from ubuntuuitoolkit import emulators as toolkit_emulators |
47 | |
48 | + |
49 | logger = logging.getLogger(__name__) |
50 | |
51 | |
52 | @@ -32,6 +35,16 @@ |
53 | |
54 | class MainView(toolkit_emulators.MainView): |
55 | |
56 | + @autopilot_logging.log_action(logger.info) |
57 | + def open_timer(self): |
58 | + """Open the Timer tab. |
59 | + |
60 | + :return: the Timer page. |
61 | + |
62 | + """ |
63 | + self.switch_to_tab('TimerTab') |
64 | + return self.wait_select_single(TimerPage) |
65 | + |
66 | # Common Emulator Functions |
67 | def _drag_page(self, page, direction): |
68 | """Function to drag the page up/down""" |
69 | @@ -65,7 +78,9 @@ |
70 | self.pointing_device.release() |
71 | |
72 | def _wait_to_stop_moving(self, page): |
73 | - page.select_single("QQuickFlickable").moving.wait_for(False) |
74 | + page.select_single( |
75 | + 'QQuickFlickable', |
76 | + objectName='animationContainer').moving.wait_for(False) |
77 | |
78 | # CLOCK Page Emulator Functions |
79 | def get_clock_page(self): |
80 | @@ -74,7 +89,8 @@ |
81 | |
82 | def get_time_label(self): |
83 | """Return the label with the timer countdown""" |
84 | - return self.select_single("ClockPage").wait_select_single("Label", objectName="label") |
85 | + return self.select_single("ClockPage").wait_select_single( |
86 | + "Label", objectName="label") |
87 | |
88 | # WORLD CLOCK Page Emulator Functions |
89 | def get_world_cities_page(self): |
90 | @@ -83,10 +99,11 @@ |
91 | |
92 | def get_search_box(self): |
93 | """Returns the search box used to search for world cities online.""" |
94 | - return self.wait_select_single('SearchBox', objectName="worldSearchBox") |
95 | + return self.wait_select_single( |
96 | + 'SearchBox', objectName="worldSearchBox") |
97 | |
98 | def get_world_cities_list(self): |
99 | - """Return the component containing the list of available world cities.""" |
100 | + """Return the component of the list of available world cities.""" |
101 | return self.wait_select_single(objectName="worldList") |
102 | |
103 | def get_city_name(self, city): |
104 | @@ -94,11 +111,15 @@ |
105 | return city.wait_select_single('Label', objectName='city_name').text |
106 | |
107 | def get_saved_cities_list(self): |
108 | - """Return the component containing list of user saved world city locations.""" |
109 | + """Return the component of the user saved world city locations.""" |
110 | return self.wait_select_single(objectName="listWorldClocks") |
111 | |
112 | def grab_first_listed_city(self): |
113 | - """Return the first city from the available world cities list (both local and online)""" |
114 | + """Return the first city from the available world cities. |
115 | + |
116 | + It returns both local and online. |
117 | + |
118 | + """ |
119 | return self.wait_select_single("Base", objectName="worldcity0") |
120 | |
121 | def select_city(self, city): |
122 | @@ -107,53 +128,19 @@ |
123 | |
124 | def grab_first_saved_city(self): |
125 | """Return the first city from the user saved world cities list""" |
126 | - return self.wait_select_single("Standard", objectName="savedworldcity0") |
127 | - |
128 | - # TIMER Page Emulator Functions |
129 | - def get_timer_reset_button(self): |
130 | - """Returns the select for the reset button""" |
131 | - return self.select_single("ImageButton", objectName="resetButtonTimer") |
132 | - |
133 | - def get_timer_name_preset(self): |
134 | - """Returns the TextField where insert the name of the preset""" |
135 | - return self.wait_select_single(LabelDots, objectName="namePreset") |
136 | - |
137 | - def get_timer_minute_hand(self): |
138 | - """Returns the hour hand of clock in timer tab""" |
139 | - return self.select_single("TimerPage").wait_select_single("DialerHand", objectName="minuteHand") |
140 | - |
141 | - def get_preset_label_text(self): |
142 | - """Returns the label with the preset text""" |
143 | - preset = self.select_many("Label", objectName="presetTextLabel") |
144 | - return preset[0] # last preset, the one created by autopilot |
145 | - |
146 | - def get_preset_label_timer(self): |
147 | - """Returns the label with the preset timer""" |
148 | - preset = self.select_many("Label", objectName="presetTimerLabel") |
149 | - return preset[0] # last preset, the one created by autopilot |
150 | - |
151 | - def get_label_timer(self): |
152 | - """Return the label with the timer countdown""" |
153 | - return self.select_single("TimerPage").wait_select_single("Label", objectName="label") |
154 | - |
155 | - def get_first_preset_list_item(self): |
156 | - """Returns the first preset list item in the timer page.""" |
157 | - return self.wait_select_single("Standard", objectName="preset0") |
158 | - |
159 | - def get_num_of_presets(self): |
160 | - """Returns the number of presets in the timer page.""" |
161 | - timer_page = self.select_single("TimerPage") |
162 | - return int(timer_page.wait_select_single("QQuickListView").count) |
163 | + return self.wait_select_single( |
164 | + "Standard", objectName="savedworldcity0") |
165 | |
166 | # STOPWATCH Page Emulator Functions |
167 | def get_stopwatch_label(self): |
168 | """Returns the select for the stopwatch label""" |
169 | - return self.select_single("StopwatchPage").wait_select_single("Label", objectName="label") |
170 | + return self.select_single( |
171 | + "StopwatchPage").wait_select_single("Label", objectName="label") |
172 | |
173 | def get_stopwatch_button(self): |
174 | """Returns the select for the stopwatch button""" |
175 | - return self.wait_select_single("StopwatchFace", |
176 | - objectName="stopwatchFace") |
177 | + return self.wait_select_single( |
178 | + "StopwatchFace", objectName="stopwatchFace") |
179 | |
180 | def get_lap_button(self): |
181 | """Returns the select for the lap button""" |
182 | @@ -350,5 +337,165 @@ |
183 | self.pointing_device.click_object(alarm) |
184 | |
185 | |
186 | +class Page(toolkit_emulators.UbuntuUIToolkitEmulatorBase): |
187 | + """Autopilot helper for Pages.""" |
188 | + |
189 | + def drag_page_up(self): |
190 | + """Drag the given page up.""" |
191 | + self._drag_page(direction='up') |
192 | + |
193 | + def drag_page_down(self): |
194 | + """Drag the given page down.""" |
195 | + self._drag_page(direction='down') |
196 | + |
197 | + def _drag_page(self, direction): |
198 | + """Function to drag the page up/down.""" |
199 | + self._wait_to_stop_moving() |
200 | + |
201 | + x, y, w, h = self.globalRect |
202 | + start_x = stop_x = x + (w / 2) |
203 | + start_y = y + (h / 2) |
204 | + |
205 | + if direction == "down": |
206 | + stop_y = start_y + h / 3 |
207 | + self.pointing_device.drag(start_x, start_y, stop_x, stop_y) |
208 | + else: |
209 | + stop_y = start_y - h / 3 |
210 | + self.pointing_device.drag(start_x, start_y, stop_x, stop_y) |
211 | + |
212 | + self._wait_to_stop_moving() |
213 | + |
214 | + def _wait_to_stop_moving(self): |
215 | + self.select_single( |
216 | + 'QQuickFlickable', |
217 | + objectName='animationContainer').moving.wait_for(False) |
218 | + |
219 | + |
220 | +class TimerPage(Page): |
221 | + """Autopilot helper for the Timer page.""" |
222 | + |
223 | + def __init__(self, *args): |
224 | + super(Page, self).__init__(*args) |
225 | + # XXX we need a better way to keep reference to the main view. |
226 | + # --elopio - 2014-01-31 |
227 | + self.main_view = self.get_root_instance().select_single(MainView) |
228 | + |
229 | + def get_num_of_presets(self): |
230 | + """Return the number of presets in the timer page.""" |
231 | + return int(self.wait_select_single('QQuickListView').count) |
232 | + |
233 | + @autopilot_logging.log_action(logger.info) |
234 | + def add_timer(self, name, set_time=False): |
235 | + self._click_add_timer_button() |
236 | + self._wait_to_stop_moving() |
237 | + if not self.main_view.wideAspect: |
238 | + self.drag_page_up() |
239 | + self._set_timer_name(name) |
240 | + if not self.main_view.wideAspect: |
241 | + self.drag_page_down() |
242 | + if set_time: |
243 | + self._set_time() |
244 | + self._click_save() |
245 | + |
246 | + def _click_add_timer_button(self): |
247 | + toolbar = self.main_view.open_toolbar() |
248 | + toolbar.click_button('addPresetButton') |
249 | + |
250 | + def _set_timer_name(self, name): |
251 | + name_label = self.wait_select_single( |
252 | + LabelDots, objectName='namePreset') |
253 | + name_label.write(name) |
254 | + if name_label.text != name: |
255 | + raise ClockEmulatorException('Failed to write the timer name.') |
256 | + |
257 | + def _set_time(self): |
258 | + # Set timer minute |
259 | + logger.debug('Grabbing minute hand') |
260 | + |
261 | + timeout = 0 |
262 | + timer_face = self.select_single('TimerFace') |
263 | + #need to select clock in order to set time |
264 | + while not timer_face.focus and timeout < 10: |
265 | + logger.debug('Timerlabel loop') |
266 | + self._click_timer_label() |
267 | + sleep(1) |
268 | + timeout += 1 |
269 | + |
270 | + # TODO we need a dialer hand emulator, with proper self-tests. |
271 | + # --elopio -2014-01-31 |
272 | + minute = self._get_timer_minute_hand() |
273 | + #make sure timer is set |
274 | + x, y, w, h = minute.globalRect |
275 | + tx = x + (w / 2) |
276 | + ty = y + (h / 2.5) |
277 | + timeout = 0 |
278 | + reset_button = self._get_timer_reset_button() |
279 | + logger.debug('reset_button %s' % reset_button.visible) |
280 | + |
281 | + #Try again if we failed at first |
282 | + while not reset_button.visible and timeout < 10: |
283 | + logger.debug('Dragging minute hand') |
284 | + self.pointing_device.drag( |
285 | + tx, ty - (h / 4), tx + (w / 2), ty + (h / 2)) |
286 | + sleep(1) |
287 | + timeout += 1 |
288 | + |
289 | + def _get_timer_minute_hand(self): |
290 | + """Return the hour hand of clock in timer tab.""" |
291 | + return self.wait_select_single('DialerHand', objectName='minuteHand') |
292 | + |
293 | + def _click_timer_label(self): |
294 | + timer_label = self._get_label_timer() |
295 | + self.pointing_device.click_object(timer_label) |
296 | + |
297 | + def _get_label_timer(self): |
298 | + """Return the label with the timer countdown.""" |
299 | + return self.select_single('Label', objectName='label') |
300 | + |
301 | + def _get_timer_reset_button(self): |
302 | + """Return the select for the reset button.""" |
303 | + return self.select_single('ImageButton', objectName='resetButtonTimer') |
304 | + |
305 | + def _click_save(self): |
306 | + toolbar = self.main_view.open_toolbar() |
307 | + toolbar.click_button('savePresetButton') |
308 | + |
309 | + def get_presets(self): |
310 | + """Return a list with the information of the presets. |
311 | + |
312 | + Each item of the returned list is a tuple of (name, time). |
313 | + |
314 | + """ |
315 | + presets = [] |
316 | + for index in range(self.get_num_of_presets()): |
317 | + text = self.select_single( |
318 | + 'Label', objectName='presetTextLabel{}'.format(index)).text |
319 | + time = self.select_single( |
320 | + 'Label', objectName='presetTimerLabel{}'.format(index)).text |
321 | + presets.append((text, time)) |
322 | + return presets |
323 | + |
324 | + @autopilot_logging.log_action(logger.info) |
325 | + def run_preset_timer(self, index): |
326 | + self._select_preset(index) |
327 | + self._click_timer_label() |
328 | + |
329 | + def _select_preset(self, index): |
330 | + presets_list = self.select_single( |
331 | + toolkit_emulators.QQuickListView, objectName='listTimerPreset') |
332 | + presets_list.click_element('preset{}'.format(index)) |
333 | + |
334 | + def get_current_time(self): |
335 | + """Return the time of the currently selected timer.""" |
336 | + self._get_label_timer().text |
337 | + |
338 | + @autopilot_logging.log_action(logger.info) |
339 | + def delete_preset_timer(self, index): |
340 | + preset = self.select_single( |
341 | + toolkit_emulators.Standard, objectName='preset{}'.format(index)) |
342 | + preset.swipe_to_delete() |
343 | + preset.confirm_removal() |
344 | + |
345 | + |
346 | class LabelDots(toolkit_emulators.TextField): |
347 | """Autopilot helper for the LabelDots component.""" |
348 | |
349 | === modified file 'tests/autopilot/ubuntu_clock_app/tests/test_clock.py' |
350 | --- tests/autopilot/ubuntu_clock_app/tests/test_clock.py 2014-02-19 12:03:16 +0000 |
351 | +++ tests/autopilot/ubuntu_clock_app/tests/test_clock.py 2014-02-24 16:24:49 +0000 |
352 | @@ -95,6 +95,7 @@ |
353 | # Get the saved world city and swipe to delete |
354 | old_saved_city_count = self.main_view.get_saved_cities_list().count |
355 | saved_city = self.main_view.grab_first_saved_city() |
356 | + self.main_view._wait_to_stop_moving(self.main_view.get_clock_page()) |
357 | saved_city.swipe_to_delete() |
358 | saved_city.confirm_removal() |
359 | |
360 | |
361 | === modified file 'tests/autopilot/ubuntu_clock_app/tests/test_timer.py' |
362 | --- tests/autopilot/ubuntu_clock_app/tests/test_timer.py 2014-02-19 18:04:36 +0000 |
363 | +++ tests/autopilot/ubuntu_clock_app/tests/test_timer.py 2014-02-24 16:24:49 +0000 |
364 | @@ -1,6 +1,6 @@ |
365 | # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
366 | # |
367 | -# Copyright (C) 2013 Canonical Ltd |
368 | +# Copyright (C) 2013, 2014 Canonical Ltd |
369 | # |
370 | # This program is free software: you can redistribute it and/or modify |
371 | # it under the terms of the GNU General Public License version 3 as |
372 | @@ -21,9 +21,8 @@ |
373 | |
374 | from __future__ import absolute_import |
375 | |
376 | -from testtools.matchers import Equals, NotEquals, Is, Not |
377 | +from testtools.matchers import Equals, NotEquals |
378 | from autopilot.matchers import Eventually |
379 | -from time import sleep |
380 | |
381 | from ubuntu_clock_app.tests import ClockAppTestCase |
382 | import logging |
383 | @@ -34,120 +33,58 @@ |
384 | class TestTimer(ClockAppTestCase): |
385 | """Tests the timer page features""" |
386 | |
387 | - """ This is needed to wait for the application to start. |
388 | - In the testfarm, the application may take some time to show up.""" |
389 | def setUp(self): |
390 | + """This is needed to wait for the application to start. |
391 | + |
392 | + In the testfarm, the application may take some time to show up. |
393 | + |
394 | + """ |
395 | super(TestTimer, self).setUp() |
396 | self.assertThat( |
397 | self.main_view.visible, Eventually(Equals(True))) |
398 | |
399 | - # Move to Timer tab |
400 | - self.main_view.switch_to_tab("TimerTab") |
401 | - |
402 | - def delete_first_preset(self): |
403 | - if not(self.main_view.wideAspect): |
404 | - self.main_view.drag_page_up("TimerPage") |
405 | - |
406 | - # Delete the preset |
407 | - first_preset = self.main_view.get_first_preset_list_item() |
408 | - first_preset.swipe_to_delete() |
409 | - first_preset.confirm_removal() |
410 | - |
411 | - def add_preset(self, setTime=0): |
412 | - # Show the toolbar |
413 | - self.main_view.open_toolbar() |
414 | - |
415 | - # Click the add preset button |
416 | - self.main_view.get_toolbar().click_button('addPresetButton') |
417 | - |
418 | - # Set Timer label as "test" |
419 | - if not(self.main_view.wideAspect): |
420 | - self.main_view.drag_page_up("TimerPage") |
421 | - label = self.main_view.get_timer_name_preset() |
422 | - label.write("AutopilotTimer") |
423 | - self.assertThat(label.text, Eventually(Equals("AutopilotTimer"))) |
424 | - if not(self.main_view.wideAspect): |
425 | - self.main_view.drag_page_down("TimerPage") |
426 | - |
427 | - if setTime: |
428 | - # Set timer minute |
429 | - logger.debug("Grabbing minute hand") |
430 | - minute = self.main_view.get_timer_minute_hand() |
431 | - timeout = 0 |
432 | - |
433 | - #need to select clock in order to set time |
434 | - while label.focus and timeout < 10: |
435 | - logger.debug("Timerlabel loop") |
436 | - TimerLabel = self.main_view.get_label_timer() |
437 | - self.pointing_device.click_object(TimerLabel) |
438 | - sleep(1) |
439 | - timeout += 1 |
440 | - |
441 | - #make sure timer is set |
442 | - x, y, w, h = minute.globalRect |
443 | - tx = x + (w / 2) |
444 | - ty = y + (h / 2.5) |
445 | - timeout = 0 |
446 | - reset_button = self.main_view.get_timer_reset_button() |
447 | - logger.debug("reset_button %s" % reset_button.visible) |
448 | - |
449 | - #Try again if we failed at first |
450 | - while not reset_button.visible and timeout < 10: |
451 | - logger.debug("Dragging minute hand") |
452 | - self.pointing_device.drag(tx, ty - (h / 4), tx + (w / 2), ty + (h / 2)) |
453 | - sleep(1) |
454 | - timeout += 1 |
455 | - |
456 | - self.main_view.open_toolbar() |
457 | - self.main_view.get_toolbar().click_button('savePresetButton') |
458 | - |
459 | - def test_add_preset(self): |
460 | - """Test to check if button to add a preset working""" |
461 | - num_of_presets_old = self.main_view.get_num_of_presets() |
462 | - self.add_preset(1) |
463 | + self.page = self.main_view.open_timer() |
464 | + |
465 | + def test_add_timer_must_add_timer_to_presets_lists(self): |
466 | + """Test to check if button to add a preset working.""" |
467 | + num_of_presets_old = self.page.get_num_of_presets() |
468 | + self.page.add_timer('test', set_time=True) |
469 | |
470 | # check that the timer preset has been added. |
471 | self.assertThat( |
472 | - self.main_view.get_num_of_presets, |
473 | + self.page.get_num_of_presets, |
474 | Eventually(Equals(num_of_presets_old + 1))) |
475 | |
476 | - def test_run_preset(self): |
477 | - """Tests if a preset can runs""" |
478 | - |
479 | - # Create a new preset |
480 | - self.add_preset() |
481 | - |
482 | - if not(self.main_view.wideAspect): |
483 | - self.main_view.drag_page_up("TimerPage") |
484 | - |
485 | - # Click to select the preset |
486 | - # FIXME: Instead of always running the first preset, run the preset which was created |
487 | - first_preset = self.main_view.get_first_preset_list_item() |
488 | - self.pointing_device.click_object(first_preset) |
489 | - |
490 | - if not(self.main_view.wideAspect): |
491 | - self.main_view.drag_page_down("TimerPage") |
492 | - |
493 | - # Click to start the preset |
494 | - label = self.main_view.get_label_timer() |
495 | - self.pointing_device.click_object(label) |
496 | - |
497 | - # Check if timer is started |
498 | - self.assertThat(label.text, Eventually(NotEquals("03:00"))) |
499 | - |
500 | - def test_delete_preset(self): |
501 | - """Test if the swipe of a preset deletes it""" |
502 | - |
503 | - # Create a new preset |
504 | - self.add_preset() |
505 | - |
506 | - num_of_presets_old = self.main_view.get_num_of_presets() |
507 | - |
508 | - #delete preset |
509 | - self.delete_first_preset() |
510 | + last_preset_name, _ = self.page.get_presets()[0] |
511 | + self.assertEqual('test', last_preset_name) |
512 | + |
513 | + def test_run_preset_must_update_timer(self): |
514 | + """Tests if a preset can run.""" |
515 | + # FIXME: Instead of always running the first preset, run the preset |
516 | + # which was created. To do this in a nice way, we should use the |
517 | + # QQuickListView but it has a bug that makes it fail in this case: |
518 | + # http://pad.lv/1275060 --elopio - 2014-01-31 |
519 | + timer_index = 0 |
520 | + _, initial_time = self.page.get_presets()[timer_index] |
521 | + if not self.main_view.wideAspect: |
522 | + self.page.drag_page_up() |
523 | + self.page.run_preset_timer(index=timer_index) |
524 | + |
525 | + self.assertThat( |
526 | + self.page.get_current_time, Eventually(NotEquals(initial_time))) |
527 | + |
528 | + def test_delete_preset_must_remove_from_presets_list(self): |
529 | + """Test if the swipe of a preset deletes it.""" |
530 | + # FIXME: Instead of always running the first preset, run the preset |
531 | + # which was created. To do this in a nice way, we should use the |
532 | + # QQuickListView but it has a bug that makes it fail in this case: |
533 | + # http://pad.lv/1275060 --elopio - 2014-01-31 |
534 | + num_of_presets_old = self.page.get_num_of_presets() |
535 | + if not self.main_view.wideAspect: |
536 | + self.page.drag_page_up() |
537 | + self.page.delete_preset_timer(index=0) |
538 | |
539 | # Check that the timer preset has been deleted |
540 | self.assertThat( |
541 | - self.main_view.get_num_of_presets, |
542 | + self.page.get_num_of_presets, |
543 | Eventually(Equals(num_of_presets_old - 1))) |
544 | - |
545 | |
546 | === modified file 'timer/PresetList.qml' |
547 | --- timer/PresetList.qml 2014-02-19 14:17:38 +0000 |
548 | +++ timer/PresetList.qml 2014-02-24 16:24:49 +0000 |
549 | @@ -54,7 +54,7 @@ |
550 | |
551 | return Utils.zeroleft(minutes, 1) + ":" + Utils.zeroleft(seconds, 2); |
552 | } |
553 | - |
554 | + |
555 | ListItem.ThinDivider { |
556 | id: divider |
557 | } |
558 | @@ -68,15 +68,16 @@ |
559 | fontSize: "medium" |
560 | } |
561 | } |
562 | - |
563 | + |
564 | ListView { |
565 | id: listTimerPreset |
566 | - |
567 | + objectName: "listTimerPreset" |
568 | + |
569 | clip: true |
570 | currentIndex: -1 |
571 | height: maxItemsVisible * units.gu(6) |
572 | anchors { left: parent.left; right: parent.right } |
573 | - |
574 | + |
575 | delegate: ListItem.Standard { |
576 | objectName: "preset" + index |
577 | Label { |
578 | @@ -88,20 +89,20 @@ |
579 | color: Theme.palette.normal.baseText |
580 | anchors { verticalCenter: parent.verticalCenter; left: parent.left; right: presetTimeLabel.left; rightMargin: units.gu(2); leftMargin: units.gu(3) } |
581 | } |
582 | - |
583 | + |
584 | Label { |
585 | id: presetTimeLabel |
586 | - objectName: "presetTimerLabel" |
587 | + objectName: "presetTimerLabel" + index |
588 | fontSize: "large" |
589 | text: getstringTimer(model.contents.duration); |
590 | color: Theme.palette.normal.baseText |
591 | anchors { verticalCenter: parent.verticalCenter; right: parent.right; rightMargin: units.gu(2) } |
592 | } |
593 | - |
594 | + |
595 | selected: listTimerPreset.currentIndex == index |
596 | removable: true |
597 | confirmRemoval: true |
598 | - |
599 | + |
600 | onItemRemoved: { |
601 | // NOTE: This causes the document to be deleted twice resulting in an error. |
602 | // The bug has been reported at https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/1276118 |
FAILED: Continuous integration, rev:318 91.189. 93.70:8080/ job/ubuntu- clock-app- ci/175/ 91.189. 93.70:8080/ job/generic- mediumtests- trusty/ 898 91.189. 93.70:8080/ job/ubuntu- clock-app- raring- amd64-ci/ 175 91.189. 93.70:8080/ job/ubuntu- clock-app- saucy-amd64- ci/175 91.189. 93.70:8080/ job/ubuntu- clock-app- trusty- amd64-ci/ 93
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: 91.189. 93.70:8080/ job/ubuntu- clock-app- ci/175/ rebuild
http://