@@ -0,0 +1,507 @@
1+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
3+# Unity Autopilot Test Suite
4+# Copyright (C) 2015 Canonical
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.
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.
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/>.
24+from autopilot import introspection
25+from ubuntuuitoolkit import UbuntuUIToolkitCustomProxyObjectBase
27+from contextlib import contextmanager
30+logger = logging.getLogger(__name__)
34+def override_proxy_timeout(proxy, timeout_seconds):
35+ original_timeout = proxy._poll_time
37+ proxy._poll_time = timeout_seconds
40+ proxy._poll_time = original_timeout
43+def get_wizard(current_page):
44+ return current_page.get_root_instance().select_single(Wizard)
47+class Wizard(UbuntuUIToolkitCustomProxyObjectBase):
48+ """High-level helper to navigate through the pages of the wizard"""
50+ def get_language_page(self):
51+ return self.wait_select_single(
52+ objectName='languagePage', visible='True')
54+ def get_current_page(self):
55+ return self.wait_select_single('Page', visible='True')
57+ def get_sim_page(self):
58+ return self.wait_select_single(
59+ objectName='simPage', visible='True')
61+ def get_password_page(self):
62+ return self.wait_select_single(
63+ objectName='passwdPage', visible='True')
65+ def get_password_entry_page(self):
66+ return self.wait_select_single(
67+ objectName='passwdSetPage', visible='True')
69+ def get_confirm_password_page(self):
70+ return self.wait_select_single(
71+ objectName='passwdConfirmPage', visible='True')
73+ def get_wifi_connect_page(self):
74+ return self.wait_select_single(
75+ objectName='wifiPage', visible='True')
77+ def get_reporting_page(self):
78+ return self.wait_select_single(
79+ objectName='reportingPage', visible='True')
81+ def get_finished_page(self):
82+ return self.wait_select_single(
83+ objectName='finishedPage', visible='True')
86+class WizardLanguagePage(UbuntuUIToolkitCustomProxyObjectBase):
87+ """Helper class to interact with the language welcome page"""
89+ # This class was renamed from LanguagePage to WizardLanguagePage because
90+ # there is a class with the same name in the system settings custom proxy
91+ # objects. Reported in http://pad.lv/1422904. --elopio - 2015-02-17
94+ def validate_dbus_object(cls, path, state):
95+ name = introspection.get_classname_from_path(path)
97+ if state['objectName'][1] == 'languagePage':
101+ def _get_language_button(self):
102+ return self.select_single(
103+ 'ComboButton', objectName='languageCombo')
105+ def _get_continue_button(self):
106+ return self.select_single('StackButton', text='Continue')
108+ def _swipe_to_language(self, list, language):
109+ """Swipe to the chosen language in the given list"""
111+ while not list.atYEnd:
113+ item = list.select_single(
114+ 'LabelVisual', text=language, visible='True')
115+ item.swipe_into_view()
117+ except introspection.dbus.StateNotFoundError:
118+ list.swipe_to_show_more_below()
119+ # item could not be found
120+ raise introspection.dbus.StateNotFoundError
122+ @autopilot.logging.log_action(logger.info)
123+ def select_language(self, language):
124+ """Select a different language from the list"""
125+ combo_button = self._get_language_button()
126+ self.pointing_device.click_object(combo_button)
127+ language_list = combo_button.wait_select_single(
128+ 'UbuntuListView11', visible='True')
129+ item = self._swipe_to_language(language_list, language)
130+ self.pointing_device.click_object(item)
132+ def get_selected_language(self):
133+ return self._get_language_button().get_properties()['text']
135+ @autopilot.logging.log_action(logger.info)
136+ def continue_(self):
137+ self.pointing_device.click_object(self._get_continue_button())
138+ wizard = get_wizard(self)
139+ next_page = wizard.get_current_page()
141+ if next_page.objectName == 'simPage':
142+ # no sim is inserted
143+ next_page = wizard.get_sim_page()
144+ sim_inserted = False
147+ next_page = wizard.get_password_page()
148+ return sim_inserted, next_page
151+class SimPage(UbuntuUIToolkitCustomProxyObjectBase):
152+ """Helper class to interact with the no sim notification page"""
155+ def validate_dbus_object(cls, path, state):
156+ name = introspection.get_classname_from_path(path)
158+ if state['objectName'][1] == 'simPage':
162+ def _get_back_button(self):
163+ return self.select_single('StackButton', text='Back')
165+ def _get_skip_button(self):
166+ return self.select_single('StackButton', text='Skip')
168+ @autopilot.logging.log_action(logger.info)
170+ self.pointing_device.click_object(self._get_back_button())
171+ return get_wizard(self).get_languge_page()
173+ @autopilot.logging.log_action(logger.info)
175+ self.pointing_device.click_object(self._get_skip_button())
176+ return get_wizard(self).get_password_page()
179+class PasswordPage(UbuntuUIToolkitCustomProxyObjectBase):
180+ """Helper class to interact with the password security page"""
182+ SECURITY_SWIPE = 'Swipe'
183+ SECURITY_PASSCODE = 'Passcode'
184+ SECURITY_PASSPHRASE = 'Passphrase'
187+ def validate_dbus_object(cls, path, state):
188+ name = introspection.get_classname_from_path(path)
190+ if state['objectName'][1] == 'passwdPage':
194+ def _get_option_name(self, formatted_name):
195+ # the option name is formatted as follows:
196+ # need to read the name between bold tags
197+ # '<b>Passcode</b> (4 digits only)'
198+ formatted_pattern = re.compile(r'<b>(.*?)</b>.*',
199+ re.IGNORECASE | re.DOTALL)
201+ match = formatted_pattern.search(formatted_name)
203+ name = match.group(1)
206+ def _get_all_options(self):
207+ return self.select_many('OptionSelectorDelegate')
209+ def _get_continue_button(self):
210+ return self.select_single('StackButton', text='Continue')
212+ def _get_back_button(self):
213+ return self.select_single('StackButton', text='Back')
215+ def _get_selected_option(self):
216+ return self.select_single(
217+ 'OptionSelectorDelegate', visible='True', selected='True')
219+ def get_selected_security_option(self):
220+ name_fmt = self._get_selected_option().get_properties()['subText']
221+ return self._get_option_name(name_fmt)
223+ @autopilot.logging.log_action(logger.info)
224+ def select_security_option(self, selected_option):
225+ options = self._get_all_options()
226+ for option in options:
227+ name = self._get_option_name(option.get_properties()['subText'])
228+ if name == selected_option:
229+ self.pointing_device.click_object(option)
231+ @autopilot.logging.log_action(logger.info)
232+ def back(self, sim_inserted):
233+ self.pointing_device.click_object(self._get_back_button())
234+ wizard = get_wizard(self)
236+ page = wizard.get_languge_page()
238+ page = wizard.get_sim_page()
241+ @autopilot.logging.log_action(logger.info)
242+ def continue_(self):
243+ option = self.get_selected_security_option()
244+ self.pointing_device.click_object(self._get_continue_button())
245+ wizard = get_wizard(self)
246+ if option == self.SECURITY_SWIPE:
247+ next_page = wizard.get_wifi_connect_page()
249+ next_page = wizard.get_password_entry_page()
253+class PasswordEntryPage(UbuntuUIToolkitCustomProxyObjectBase):
254+ """Helper class to interact with the pin entry page"""
257+ def validate_dbus_object(cls, path, state):
258+ name = introspection.get_classname_from_path(path)
260+ if state['objectName'][1] == 'passwdSetPage':
264+ def _get_pinpad_button(self, char):
265+ return self.select_single('PinPadButton', text=char)
267+ def _get_continue_button(self):
268+ return self.select_single('StackButton', text='Continue')
270+ def _get_back_button(self):
271+ return self.select_single('StackButton', text='Back')
273+ def _get_text_field(self):
274+ return self.select_single('QQuickTextInput')
276+ @autopilot.logging.log_action(logger.info)
277+ def enter_pin(self, pin):
279+ self.pointing_device.click_object(self._get_pinpad_button(char))
280+ return get_wizard(self).get_confirm_password_page()
282+ @autopilot.logging.log_action(logger.info)
283+ def enter_text(self, text):
284+ self.pointing_device.click_object(self._get_text_field())
285+ autopilot.input.Keyboard.create().type(text)
287+ @autopilot.logging.log_action(logger.info)
289+ self.pointing_device.click_object(self._get_back_button())
290+ return get_wizard(self).get_password_page()
292+ @autopilot.logging.log_action(logger.info)
293+ def continue_(self):
294+ autopilot.input.Keyboard.create().press_and_release('Enter')
295+ return get_wizard(self).get_confirm_password_page()
298+class ConfirmPasswordPage(UbuntuUIToolkitCustomProxyObjectBase):
299+ """Helper class to interact with the pin confirmation page"""
302+ def validate_dbus_object(cls, path, state):
303+ name = introspection.get_classname_from_path(path)
305+ if state['objectName'][1] == 'passwdConfirmPage':
309+ def _get_pinpad_button(self, char):
310+ return self.select_single('PinPadButton', text=char)
312+ def _get_continue_button(self):
313+ return self.select_single('StackButton', text='Continue')
315+ def _get_back_button(self):
316+ return self.select_single('StackButton', text='Back')
318+ def _get_text_field(self):
319+ return self.select_single('QQuickTextInput')
321+ @autopilot.logging.log_action(logger.info)
322+ def enter_pin(self, pin):
324+ self.pointing_device.click_object(self._get_pinpad_button(char))
325+ return get_wizard(self).get_wifi_connect_page()
327+ @autopilot.logging.log_action(logger.info)
328+ def enter_text(self, text):
329+ self.pointing_device.click_object(self._get_text_field())
330+ autopilot.input.Keyboard.create().type(text)
332+ @autopilot.logging.log_action(logger.info)
334+ self.pointing_device.click_object(self._get_back_button())
335+ return get_wizard(self).get_password_page()
337+ @autopilot.logging.log_action(logger.info)
338+ def continue_(self):
339+ autopilot.input.Keyboard.create().press_and_release('Enter')
340+ return get_wizard(self).get_wifi_connect_page()
343+class WifiConnectPage(UbuntuUIToolkitCustomProxyObjectBase):
344+ """Helper class to interact with the Wi-Fi network list page"""
347+ def validate_dbus_object(cls, path, state):
348+ name = introspection.get_classname_from_path(path)
350+ if state['objectName'][1] == 'wifiPage':
354+ def _get_all_networks(self):
356+ networks = self.select_many('Standard', objectName='accessPoint',
362+ def _get_network(self, ssid):
363+ return self.wait_select_single(
364+ 'Standard', objectName='accessPoint', text=ssid, visible='True')
366+ def _get_network_checkbox(self, ssid):
367+ return self._get_network(ssid).select_single(
368+ 'CheckBox', visible='True')
370+ def _get_notification(self, unity):
371+ logger.info('Waiting longer for notification object')
372+ with override_proxy_timeout(unity, 30):
373+ return unity.wait_select_single(
374+ Notification, objectName='notification1', visible='True')
376+ def _get_back_button(self):
377+ return self.wait_select_single(
378+ 'StackButton', text='Back', visible='True')
380+ def _get_skip_button(self):
381+ return self.wait_select_single(
382+ 'StackButton', text='Skip', visible='True')
384+ def _get_continue_button(self):
385+ return self.wait_select_single(
386+ 'StackButton', text='Continue', visible='True')
388+ def is_any_network_checked(self):
389+ networks = self._get_all_networks()
390+ for network in networks:
391+ checkbox = network.select_single('CheckBox', visible='True')
392+ if checkbox.get_properties()['checked']:
396+ def is_any_network_found(self):
397+ num_neworks = len(self._get_all_networks())
398+ return True if num_neworks > 0 else False
400+ def is_network_checked(self, ssid):
401+ return self._get_network_checkbox(ssid).get_properties()['checked']
403+ @autopilot.logging.log_action(logger.info)
404+ def select_network(self, unity, ssid):
405+ self.pointing_device.click_object(self._get_network_checkbox(ssid))
406+ return PasswordNotification(self._get_notification(unity))
408+ @autopilot.logging.log_action(logger.info)
410+ self.pointing_device.click_object(self._get_back_button())
411+ return get_wizard(self).get_password_page()
413+ @autopilot.logging.log_action(logger.info)
415+ self.pointing_device.click_object(self._get_skip_button())
416+ return get_wizard(self).get_reporting_page()
418+ @autopilot.logging.log_action(logger.info)
419+ def continue_(self):
420+ self.pointing_device.click_object(self._get_continue_button())
421+ return get_wizard(self).get_reporting_page()
424+class Notification(UbuntuUIToolkitCustomProxyObjectBase):
425+ """Base class for notification objects"""
429+class PasswordNotification(Notification):
430+ """Helper class to interact with the password entry notification"""
432+ def __init__(self, notification):
433+ self.notification = notification
435+ def _get_connect_button(self):
436+ return self.notification.wait_select_single(
437+ 'Button', text='Connect', objectName='notify_button0')
439+ def _get_cancel_buttoon(self):
440+ return self.notification.wait_select_single(
441+ 'Button', text='Cancel', objectName='notify_button1')
443+ def _get_text_field(self):
444+ return self.notification.wait_select_single('TextField')
446+ @autopilot.logging.log_action(logger.info)
447+ def enter_text(self, text):
448+ self._get_text_field().write(text)
450+ @autopilot.logging.log_action(logger.info)
452+ self.notification.pointing_device.click_object(
453+ self._get_connect_button())
455+ @autopilot.logging.log_action(logger.info)
457+ self.notification.pointing_device.click_object(
458+ self._get_cancel_buttoon())
461+class ReportingPage(UbuntuUIToolkitCustomProxyObjectBase):
462+ """Helper class to interact with the reporting page"""
465+ def validate_dbus_object(cls, path, state):
466+ name = introspection.get_classname_from_path(path)
468+ if state['objectName'][1] == 'reportingPage':
472+ def _get_continue_button(self):
473+ return self.select_single('StackButton', text='Continue')
475+ def _get_back_button(self):
476+ return self.select_single('StackButton', text='Back')
478+ @autopilot.logging.log_action(logger.info)
480+ self.pointing_device.click_object(self._get_back_button())
481+ return get_wizard(self).get_wifi_connect_page()
483+ @autopilot.logging.log_action(logger.info)
484+ def continue_(self):
485+ self.pointing_device.click_object(self._get_continue_button())
486+ return get_wizard(self).get_finished_page()
489+class FinishedPage(UbuntuUIToolkitCustomProxyObjectBase):
490+ """Helper class to interact with the finished page"""
493+ def validate_dbus_object(cls, path, state):
494+ name = introspection.get_classname_from_path(path)
496+ if state['objectName'][1] == 'finishedPage':
500+ def _get_finish_button(self):
501+ return self.wait_select_single(
502+ 'StackButton', text='Finish', visible='True')
504+ @autopilot.logging.log_action(logger.info)
506+ self.pointing_device.click_object(self._get_finish_button())
507+ self.wait_until_destroyed()