Unity 8
__init__.py
1 # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2 #
3 # Unity Autopilot Test Suite
4 # Copyright (C) 2015 Canonical
5 #
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #
19 
20 import logging
21 import re
22 
23 import autopilot
24 from autopilot import introspection
25 from ubuntuuitoolkit import UbuntuUIToolkitCustomProxyObjectBase
26 
27 from contextlib import contextmanager
28 
29 
30 logger = logging.getLogger(__name__)
31 
32 
33 @contextmanager
34 def override_proxy_timeout(proxy, timeout_seconds):
35  original_timeout = proxy._poll_time
36  try:
37  proxy._poll_time = timeout_seconds
38  yield proxy
39  finally:
40  proxy._poll_time = original_timeout
41 
42 
43 def get_wizard(current_page):
44  return current_page.get_root_instance().select_single(Wizard)
45 
46 
47 class Wizard(UbuntuUIToolkitCustomProxyObjectBase):
48  """High-level helper to navigate through the pages of the wizard"""
49 
50  def get_language_page(self):
51  return self.wait_select_single(
52  objectName='languagePage', visible='True')
53 
54  def get_current_page(self):
55  return self.wait_select_single('Page', visible='True')
56 
57  def get_sim_page(self):
58  return self.wait_select_single(
59  objectName='simPage', visible='True')
60 
61  def get_password_page(self):
62  return self.wait_select_single(
63  objectName='passwdPage', visible='True')
64 
65  def get_password_entry_page(self):
66  return self.wait_select_single(
67  objectName='passwdSetPage', visible='True')
68 
69  def get_confirm_password_page(self):
70  return self.wait_select_single(
71  objectName='passwdConfirmPage', visible='True')
72 
73  def get_wifi_connect_page(self):
74  return self.wait_select_single(
75  objectName='wifiPage', visible='True')
76 
77  def get_location_page(self):
78  return self.wait_select_single(
79  objectName='locationPage', visible='True')
80 
81  def get_reporting_page(self):
82  return self.wait_select_single(
83  objectName='reportingPage', visible='True')
84 
85  def get_finished_page(self):
86  return self.wait_select_single(
87  objectName='finishedPage', visible='True')
88 
89 
90 class WizardLanguagePage(UbuntuUIToolkitCustomProxyObjectBase):
91  """Helper class to interact with the language welcome page"""
92 
93  # This class was renamed from LanguagePage to WizardLanguagePage because
94  # there is a class with the same name in the system settings custom proxy
95  # objects. Reported in http://pad.lv/1422904. --elopio - 2015-02-17
96 
97  @classmethod
98  def validate_dbus_object(cls, path, state):
99  name = introspection.get_classname_from_path(path)
100  if name == b'Page':
101  if state['objectName'][1] == 'languagePage':
102  return True
103  return False
104 
105  def _get_language_button(self):
106  return self.select_single(
107  'ComboButton', objectName='languageCombo')
108 
109  def _get_continue_button(self):
110  return self.select_single('StackButton', text='Continue')
111 
112  def _swipe_to_language(self, list, language):
113  """Swipe to the chosen language in the given list"""
114  list.swipe_to_top()
115  while not list.atYEnd:
116  try:
117  item = list.select_single(
118  'LabelVisual', text=language, visible='True')
119  item.swipe_into_view()
120  return item
121  except introspection.dbus.StateNotFoundError:
122  list.swipe_to_show_more_below()
123  # item could not be found
124  raise introspection.dbus.StateNotFoundError
125 
126  @autopilot.logging.log_action(logger.info)
127  def select_language(self, language):
128  """Select a different language from the list"""
129  combo_button = self._get_language_button()
130  self.pointing_device.click_object(combo_button)
131  language_list = combo_button.wait_select_single(
132  'UbuntuListView11', visible='True')
133  item = self._swipe_to_language(language_list, language)
134  self.pointing_device.click_object(item)
135 
136  def get_selected_language(self):
137  return self._get_language_button().get_properties()['text']
138 
139  @autopilot.logging.log_action(logger.info)
140  def continue_(self):
141  self.pointing_device.click_object(self._get_continue_button())
142  wizard = get_wizard(self)
143  next_page = wizard.get_current_page()
144  sim_inserted = True
145  if next_page.objectName == 'simPage':
146  # no sim is inserted
147  next_page = wizard.get_sim_page()
148  sim_inserted = False
149  else:
150  # sim is inserted
151  next_page = wizard.get_password_page()
152  return sim_inserted, next_page
153 
154 
155 class SimPage(UbuntuUIToolkitCustomProxyObjectBase):
156  """Helper class to interact with the no sim notification page"""
157 
158  @classmethod
159  def validate_dbus_object(cls, path, state):
160  name = introspection.get_classname_from_path(path)
161  if name == b'Page':
162  if state['objectName'][1] == 'simPage':
163  return True
164  return False
165 
166  def _get_back_button(self):
167  return self.select_single('StackButton', text='Back')
168 
169  def _get_skip_button(self):
170  return self.select_single('StackButton', text='Skip')
171 
172  @autopilot.logging.log_action(logger.info)
173  def back(self):
174  self.pointing_device.click_object(self._get_back_button())
175  return get_wizard(self).get_languge_page()
176 
177  @autopilot.logging.log_action(logger.info)
178  def skip(self):
179  self.pointing_device.click_object(self._get_skip_button())
180  return get_wizard(self).get_password_page()
181 
182 
183 class PasswordPage(UbuntuUIToolkitCustomProxyObjectBase):
184  """Helper class to interact with the password security page"""
185 
186  SECURITY_SWIPE = 'Swipe'
187  SECURITY_PASSCODE = 'Passcode'
188  SECURITY_PASSPHRASE = 'Passphrase'
189 
190  @classmethod
191  def validate_dbus_object(cls, path, state):
192  name = introspection.get_classname_from_path(path)
193  if name == b'Page':
194  if state['objectName'][1] == 'passwdPage':
195  return True
196  return False
197 
198  def _get_option_name(self, formatted_name):
199  # the option name is formatted as follows:
200  # need to read the name between bold tags
201  # '<b>Passcode</b> (4 digits only)'
202  formatted_pattern = re.compile(r'<b>(.*?)</b>.*',
203  re.IGNORECASE | re.DOTALL)
204  name = None
205  match = formatted_pattern.search(formatted_name)
206  if match:
207  name = match.group(1)
208  return name
209 
210  def _get_all_options(self):
211  return self.select_many('OptionSelectorDelegate')
212 
213  def _get_continue_button(self):
214  return self.select_single('StackButton', text='Continue')
215 
216  def _get_back_button(self):
217  return self.select_single('StackButton', text='Back')
218 
219  def _get_selected_option(self):
220  return self.select_single(
221  'OptionSelectorDelegate', visible='True', selected='True')
222 
223  def get_selected_security_option(self):
224  name_fmt = self._get_selected_option().get_properties()['subText']
225  return self._get_option_name(name_fmt)
226 
227  @autopilot.logging.log_action(logger.info)
228  def select_security_option(self, selected_option):
229  options = self._get_all_options()
230  for option in options:
231  name = self._get_option_name(option.get_properties()['subText'])
232  if name == selected_option:
233  self.pointing_device.click_object(option)
234 
235  @autopilot.logging.log_action(logger.info)
236  def back(self, sim_inserted):
237  self.pointing_device.click_object(self._get_back_button())
238  wizard = get_wizard(self)
239  if sim_inserted:
240  page = wizard.get_languge_page()
241  else:
242  page = wizard.get_sim_page()
243  return page
244 
245  @autopilot.logging.log_action(logger.info)
246  def continue_(self):
247  option = self.get_selected_security_option()
248  self.pointing_device.click_object(self._get_continue_button())
249  wizard = get_wizard(self)
250  if option == self.SECURITY_SWIPE:
251  next_page = wizard.get_wifi_connect_page()
252  else:
253  next_page = wizard.get_password_entry_page()
254  return next_page
255 
256 
257 class PasswordEntryPage(UbuntuUIToolkitCustomProxyObjectBase):
258  """Helper class to interact with the pin entry page"""
259 
260  @classmethod
261  def validate_dbus_object(cls, path, state):
262  name = introspection.get_classname_from_path(path)
263  if name == b'Page':
264  if state['objectName'][1] == 'passwdSetPage':
265  return True
266  return False
267 
268  def _get_pinpad_button(self, char):
269  return self.select_single('PinPadButton', text=char)
270 
271  def _get_continue_button(self):
272  return self.select_single('StackButton', text='Continue')
273 
274  def _get_back_button(self):
275  return self.select_single('StackButton', text='Back')
276 
277  def _get_text_field(self):
278  return self.select_single('QQuickTextInput')
279 
280  @autopilot.logging.log_action(logger.info)
281  def enter_pin(self, pin):
282  for char in pin:
283  self.pointing_device.click_object(self._get_pinpad_button(char))
284  return get_wizard(self).get_confirm_password_page()
285 
286  @autopilot.logging.log_action(logger.info)
287  def enter_text(self, text):
288  self.pointing_device.click_object(self._get_text_field())
289  autopilot.input.Keyboard.create().type(text)
290 
291  @autopilot.logging.log_action(logger.info)
292  def back(self):
293  self.pointing_device.click_object(self._get_back_button())
294  return get_wizard(self).get_password_page()
295 
296  @autopilot.logging.log_action(logger.info)
297  def continue_(self):
298  autopilot.input.Keyboard.create().press_and_release('Enter')
299  return get_wizard(self).get_confirm_password_page()
300 
301 
302 class ConfirmPasswordPage(UbuntuUIToolkitCustomProxyObjectBase):
303  """Helper class to interact with the pin confirmation page"""
304 
305  @classmethod
306  def validate_dbus_object(cls, path, state):
307  name = introspection.get_classname_from_path(path)
308  if name == b'Page':
309  if state['objectName'][1] == 'passwdConfirmPage':
310  return True
311  return False
312 
313  def _get_pinpad_button(self, char):
314  return self.select_single('PinPadButton', text=char)
315 
316  def _get_continue_button(self):
317  return self.select_single('StackButton', text='Continue')
318 
319  def _get_back_button(self):
320  return self.select_single('StackButton', text='Back')
321 
322  def _get_text_field(self):
323  return self.select_single('QQuickTextInput')
324 
325  @autopilot.logging.log_action(logger.info)
326  def enter_pin(self, pin):
327  for char in pin:
328  self.pointing_device.click_object(self._get_pinpad_button(char))
329  return get_wizard(self).get_wifi_connect_page()
330 
331  @autopilot.logging.log_action(logger.info)
332  def enter_text(self, text):
333  self.pointing_device.click_object(self._get_text_field())
334  autopilot.input.Keyboard.create().type(text)
335 
336  @autopilot.logging.log_action(logger.info)
337  def back(self):
338  self.pointing_device.click_object(self._get_back_button())
339  return get_wizard(self).get_password_page()
340 
341  @autopilot.logging.log_action(logger.info)
342  def continue_(self):
343  autopilot.input.Keyboard.create().press_and_release('Enter')
344  return get_wizard(self).get_wifi_connect_page()
345 
346 
347 class WifiConnectPage(UbuntuUIToolkitCustomProxyObjectBase):
348  """Helper class to interact with the Wi-Fi network list page"""
349 
350  @classmethod
351  def validate_dbus_object(cls, path, state):
352  name = introspection.get_classname_from_path(path)
353  if name == b'Page':
354  if state['objectName'][1] == 'wifiPage':
355  return True
356  return False
357 
358  def _get_all_networks(self):
359  try:
360  networks = self.select_many('Standard', objectName='accessPoint',
361  visible='True')
362  except:
363  networks = []
364  return networks
365 
366  def _get_network(self, ssid):
367  return self.wait_select_single(
368  'Standard', objectName='accessPoint', text=ssid, visible='True')
369 
370  def _get_network_checkbox(self, ssid):
371  return self._get_network(ssid).select_single(
372  'CheckBox', visible='True')
373 
374  def _get_next_page(self):
375  wizard = get_wizard(self)
376  next_page = wizard.get_current_page()
377  locationPageEnabled = True
378  reportingPageEnabled = True
379  if next_page.objectName == 'locationPage':
380  next_page = wizard.get_location_page()
381  else:
382  locationPageEnabled = False
383  if next_page.objectName == 'reportingPage':
384  next_page = wizard.get_reporting_page()
385  else:
386  reportingPageEnabled = False
387  next_page = wizard.get_finished_page()
388  return locationPageEnabled, reportingPageEnabled, next_page
389 
390  def _get_notification(self, unity):
391  logger.info('Waiting longer for notification object')
392  with override_proxy_timeout(unity, 30):
393  return unity.wait_select_single(
394  Notification, objectName='notification1', visible='True')
395 
396  def _get_back_button(self):
397  return self.wait_select_single(
398  'StackButton', text='Back', visible='True')
399 
400  def _get_continue_button(self):
401  return self.wait_select_single(
402  'StackButton', text='Continue', visible='True')
403 
404  def _get_skip_button(self):
405  return self.wait_select_single(
406  'StackButton', text='Skip', visible='True')
407 
408  def is_any_network_checked(self):
409  networks = self._get_all_networks()
410  for network in networks:
411  checkbox = network.select_single('CheckBox', visible='True')
412  if checkbox.get_properties()['checked']:
413  return True
414  return False
415 
416  def is_any_network_found(self):
417  num_neworks = len(self._get_all_networks())
418  return True if num_neworks > 0 else False
419 
420  def is_network_checked(self, ssid):
421  return self._get_network_checkbox(ssid).get_properties()['checked']
422 
423  @autopilot.logging.log_action(logger.info)
424  def select_network(self, unity, ssid):
425  self.pointing_device.click_object(self._get_network_checkbox(ssid))
426  return PasswordNotification(self._get_notification(unity))
427 
428  @autopilot.logging.log_action(logger.info)
429  def back(self):
430  self.pointing_device.click_object(self._get_back_button())
431  return get_wizard(self).get_password_page()
432 
433  @autopilot.logging.log_action(logger.info)
434  def skip(self):
435  self.pointing_device.click_object(self._get_skip_button())
436  return self._get_next_page()
437 
438  @autopilot.logging.log_action(logger.info)
439  def continue_(self):
440  self.pointing_device.click_object(self._get_continue_button())
441  return self._get_next_page()
442 
443 
444 class LocationPage(UbuntuUIToolkitCustomProxyObjectBase):
445  """Helper class to interact with the LocationPage"""
446 
447  @classmethod
448  def validate_dbus_object(cls, path, state):
449  name = introspection.get_classname_from_path(path)
450  if name == b'Page':
451  if state['objectName'][1] == 'locationPage':
452  return True
453  return False
454 
455  def _get_back_button(self):
456  return self.select_single('StackButton', text='Back')
457 
458  def _get_continue_button(self):
459  return self.select_single('StackButton', text='Continue')
460 
461  @autopilot.logging.log_action(logger.info)
462  def back(self):
463  self.pointing_device.click_object(self._get_back_button())
464  return get_wizard(self).get_wifi_connect_page()
465 
466  @autopilot.logging.log_action(logger.info)
467  def continue_(self):
468  self.pointing_device.click_object(self._get_continue_button())
469  return get_wizard(self).get_reporting_page()
470 
471 
472 class Notification(UbuntuUIToolkitCustomProxyObjectBase):
473  """Base class for notification objects"""
474  pass
475 
476 
477 class PasswordNotification(Notification):
478  """Helper class to interact with the password entry notification"""
479 
480  def __init__(self, notification):
481  self.notification = notification
482 
483  def _get_connect_button(self):
484  return self.notification.wait_select_single(
485  'Button', text='Connect', objectName='notify_button0')
486 
487  def _get_cancel_buttoon(self):
488  return self.notification.wait_select_single(
489  'Button', text='Cancel', objectName='notify_button1')
490 
491  def _get_text_field(self):
492  return self.notification.wait_select_single('TextField')
493 
494  @autopilot.logging.log_action(logger.info)
495  def enter_text(self, text):
496  self._get_text_field().write(text)
497 
498  @autopilot.logging.log_action(logger.info)
499  def connect(self):
500  self.notification.pointing_device.click_object(
501  self._get_connect_button())
502 
503  @autopilot.logging.log_action(logger.info)
504  def cancel(self):
505  self.notification.pointing_device.click_object(
506  self._get_cancel_buttoon())
507 
508 
509 class ReportingPage(UbuntuUIToolkitCustomProxyObjectBase):
510  """Helper class to interact with the reporting page"""
511 
512  @classmethod
513  def validate_dbus_object(cls, path, state):
514  name = introspection.get_classname_from_path(path)
515  if name == b'Page':
516  if state['objectName'][1] == 'reportingPage':
517  return True
518  return False
519 
520  def _get_continue_button(self):
521  return self.select_single('StackButton', text='Continue')
522 
523  def _get_back_button(self):
524  return self.select_single('StackButton', text='Back')
525 
526  @autopilot.logging.log_action(logger.info)
527  def back(self):
528  self.pointing_device.click_object(self._get_back_button())
529  return get_wizard(self).get_wifi_connect_page()
530 
531  @autopilot.logging.log_action(logger.info)
532  def continue_(self):
533  self.pointing_device.click_object(self._get_continue_button())
534  return get_wizard(self).get_finished_page()
535 
536 
537 class FinishedPage(UbuntuUIToolkitCustomProxyObjectBase):
538  """Helper class to interact with the finished page"""
539 
540  @classmethod
541  def validate_dbus_object(cls, path, state):
542  name = introspection.get_classname_from_path(path)
543  if name == b'Page':
544  if state['objectName'][1] == 'finishedPage':
545  return True
546  return False
547 
548  def _get_finish_button(self):
549  return self.wait_select_single(
550  'StackButton', text='Finish', visible='True')
551 
552  @autopilot.logging.log_action(logger.info)
553  def finish(self):
554  self.pointing_device.click_object(self._get_finish_button())
555  self.wait_until_destroyed()
def _get_option_name(self, formatted_name)
Definition: __init__.py:198
def _get_text_field(self)
Definition: __init__.py:277
Definition: __init__.py:257
def _get_back_button(self)
Definition: __init__.py:274
def _swipe_to_language(self, list, language)
Definition: __init__.py:112
def _get_pinpad_button(self, char)
Definition: __init__.py:268