@@ -0,0 +1,473 @@
1+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
3+# Copyright 2015 Canonical Ltd.
5+# This program is free software; you can redistribute it and/or modify
6+# it under the terms of the GNU General Public License version 3, as published
7+# by the Free Software Foundation.
9+# This program is distributed in the hope that it will be useful,
10+# but WITHOUT ANY WARRANTY; without even the implied warranty of
11+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+# GNU General Public License for more details.
14+# You should have received a copy of the GNU General Public License
15+# along with this program. If not, see <http://www.gnu.org/licenses/>
21+from autopilot import introspection
22+from ubuntuuitoolkit import UbuntuUIToolkitCustomProxyObjectBase
24+from unity8.settings_wizard import override_proxy_timeout
26+logger = logging.getLogger(__name__)
29+def get_wizard(current_page):
30+ return current_page.get_root_instance().select_single(Wizard)
33+class Wizard(UbuntuUIToolkitCustomProxyObjectBase):
34+ """High-level helper to navigate through the pages of the wizard"""
36+ def get_language_page(self):
37+ return self.wait_select_single(
38+ objectName='languagePage', visible='True')
40+ def get_current_page(self):
41+ return self.wait_select_single('Page', visible='True')
43+ def get_sim_page(self):
44+ return self.wait_select_single(
45+ objectName='simPage', visible='True')
47+ def get_password_page(self):
48+ return self.wait_select_single(
49+ objectName='passwdPage', visible='True')
51+ def get_password_entry_page(self):
52+ return self.wait_select_single(
53+ objectName='passwdSetPage', visible='True')
55+ def get_confirm_password_page(self):
56+ return self.wait_select_single(
57+ objectName='passwdConfirmPage', visible='True')
59+ def get_wifi_connect_page(self):
60+ return self.wait_select_single(
61+ objectName='wifiPage', visible='True')
63+ def get_reporting_page(self):
64+ return self.wait_select_single(
65+ objectName='reportingPage', visible='True')
67+ def get_finished_page(self):
68+ return self.wait_select_single(
69+ objectName='finishedPage', visible='True')
72+class WizardLanguagePage(UbuntuUIToolkitCustomProxyObjectBase):
73+ """Helper class to interact with the language welcome page"""
75+ # This class was renamed from LanguagePage to WizardLanguagePage because
76+ # there is a class with the same name in the system settings custom proxy
77+ # objects. Reported in http://pad.lv/1422904. --elopio - 2015-02-17
80+ def validate_dbus_object(cls, path, state):
81+ name = introspection.get_classname_from_path(path)
83+ if state['objectName'][1] == 'languagePage':
87+ def _get_language_button(self):
88+ return self.select_single(
89+ 'ComboButton', objectName='languageCombo')
91+ def _get_continue_button(self):
92+ return self.select_single('StackButton', text='Continue')
94+ def _swipe_to_language(self, list, language):
95+ """Swipe to the chosen language in the given list"""
97+ while not list.atYEnd:
99+ item = list.select_single(
100+ 'LabelVisual', text=language, visible='True')
101+ item.swipe_into_view()
103+ except introspection.dbus.StateNotFoundError:
104+ list.swipe_to_show_more_below()
105+ # item could not be found
106+ raise introspection.dbus.StateNotFoundError
108+ @autopilot.logging.log_action(logger.info)
109+ def select_language(self, language):
110+ """Select a different language from the list"""
111+ combo_button = self._get_language_button()
112+ self.pointing_device.click_object(combo_button)
113+ language_list = combo_button.wait_select_single(
114+ 'UbuntuListView11', visible='True')
115+ item = self._swipe_to_language(language_list, language)
116+ self.pointing_device.click_object(item)
118+ def get_selected_language(self):
119+ return self._get_language_button().get_properties()['text']
121+ @autopilot.logging.log_action(logger.info)
122+ def continue_(self):
123+ self.pointing_device.click_object(self._get_continue_button())
124+ wizard = get_wizard(self)
125+ next_page = wizard.get_current_page()
127+ if next_page.objectName == 'simPage':
128+ # no sim is inserted
129+ next_page = wizard.get_sim_page()
130+ sim_inserted = False
133+ next_page = wizard.get_password_page()
134+ return sim_inserted, next_page
137+class SimPage(UbuntuUIToolkitCustomProxyObjectBase):
138+ """Helper class to interact with the no sim notification page"""
141+ def validate_dbus_object(cls, path, state):
142+ name = introspection.get_classname_from_path(path)
144+ if state['objectName'][1] == 'simPage':
148+ def _get_back_button(self):
149+ return self.select_single('StackButton', text='Back')
151+ def _get_skip_button(self):
152+ return self.select_single('StackButton', text='Skip')
154+ @autopilot.logging.log_action(logger.info)
156+ self.pointing_device.click_object(self._get_back_button())
157+ return get_wizard(self).get_languge_page()
159+ @autopilot.logging.log_action(logger.info)
161+ self.pointing_device.click_object(self._get_skip_button())
162+ return get_wizard(self).get_password_page()
165+class PasswordPage(UbuntuUIToolkitCustomProxyObjectBase):
166+ """Helper class to interact with the password security page"""
168+ SECURITY_SWIPE = 'Swipe'
169+ SECURITY_PASSCODE = 'Passcode'
170+ SECURITY_PASSPHRASE = 'Passphrase'
173+ def validate_dbus_object(cls, path, state):
174+ name = introspection.get_classname_from_path(path)
176+ if state['objectName'][1] == 'passwdPage':
180+ def _get_option_name(self, formatted_name):
181+ # the option name is formatted as follows:
182+ # need to read the name between bold tags
183+ # '<b>Passcode</b> (4 digits only)'
184+ formatted_pattern = re.compile(r'<b>(.*?)</b>.*',
185+ re.IGNORECASE | re.DOTALL)
187+ match = formatted_pattern.search(formatted_name)
189+ name = match.group(1)
192+ def _get_all_options(self):
193+ return self.select_many('OptionSelectorDelegate')
195+ def _get_continue_button(self):
196+ return self.select_single('StackButton', text='Continue')
198+ def _get_back_button(self):
199+ return self.select_single('StackButton', text='Back')
201+ def _get_selected_option(self):
202+ return self.select_single(
203+ 'OptionSelectorDelegate', visible='True', selected='True')
205+ def get_selected_security_option(self):
206+ name_fmt = self._get_selected_option().get_properties()['subText']
207+ return self._get_option_name(name_fmt)
209+ @autopilot.logging.log_action(logger.info)
210+ def select_security_option(self, selected_option):
211+ options = self._get_all_options()
212+ for option in options:
213+ name = self._get_option_name(option.get_properties()['subText'])
214+ if name == selected_option:
215+ self.pointing_device.click_object(option)
217+ @autopilot.logging.log_action(logger.info)
218+ def back(self, sim_inserted):
219+ self.pointing_device.click_object(self._get_back_button())
220+ wizard = get_wizard(self)
222+ page = wizard.get_languge_page()
224+ page = wizard.get_sim_page()
227+ @autopilot.logging.log_action(logger.info)
228+ def continue_(self):
229+ option = self.get_selected_security_option()
230+ self.pointing_device.click_object(self._get_continue_button())
231+ wizard = get_wizard(self)
232+ if option == self.SECURITY_SWIPE:
233+ next_page = wizard.get_wifi_connect_page()
235+ next_page = wizard.get_password_entry_page()
239+class PasswordEntryPage(UbuntuUIToolkitCustomProxyObjectBase):
240+ """Helper class to interact with the pin entry page"""
243+ def validate_dbus_object(cls, path, state):
244+ name = introspection.get_classname_from_path(path)
246+ if state['objectName'][1] == 'passwdSetPage':
250+ def _get_pinpad_button(self, char):
251+ return self.select_single('PinPadButton', text=char)
253+ def _get_continue_button(self):
254+ return self.select_single('StackButton', text='Continue')
256+ def _get_back_button(self):
257+ return self.select_single('StackButton', text='Back')
259+ def _get_text_field(self):
260+ return self.select_single('QQuickTextInput')
262+ @autopilot.logging.log_action(logger.info)
263+ def enter_pin(self, pin):
265+ self.pointing_device.click_object(self._get_pinpad_button(char))
266+ return get_wizard(self).get_confirm_password_page()
268+ @autopilot.logging.log_action(logger.info)
269+ def enter_text(self, text):
270+ self.pointing_device.click_object(self._get_text_field())
271+ autopilot.input.Keyboard.create().type(text)
273+ @autopilot.logging.log_action(logger.info)
275+ self.pointing_device.click_object(self._get_back_button())
276+ return get_wizard(self).get_password_page()
278+ @autopilot.logging.log_action(logger.info)
279+ def continue_(self):
280+ autopilot.input.Keyboard.create().press_and_release('Enter')
281+ return get_wizard(self).get_confirm_password_page()
284+class ConfirmPasswordPage(UbuntuUIToolkitCustomProxyObjectBase):
285+ """Helper class to interact with the pin confirmation page"""
288+ def validate_dbus_object(cls, path, state):
289+ name = introspection.get_classname_from_path(path)
291+ if state['objectName'][1] == 'passwdConfirmPage':
295+ def _get_pinpad_button(self, char):
296+ return self.select_single('PinPadButton', text=char)
298+ def _get_continue_button(self):
299+ return self.select_single('StackButton', text='Continue')
301+ def _get_back_button(self):
302+ return self.select_single('StackButton', text='Back')
304+ def _get_text_field(self):
305+ return self.select_single('QQuickTextInput')
307+ @autopilot.logging.log_action(logger.info)
308+ def enter_pin(self, pin):
310+ self.pointing_device.click_object(self._get_pinpad_button(char))
311+ return get_wizard(self).get_wifi_connect_page()
313+ @autopilot.logging.log_action(logger.info)
314+ def enter_text(self, text):
315+ self.pointing_device.click_object(self._get_text_field())
316+ autopilot.input.Keyboard.create().type(text)
318+ @autopilot.logging.log_action(logger.info)
320+ self.pointing_device.click_object(self._get_back_button())
321+ return get_wizard(self).get_password_page()
323+ @autopilot.logging.log_action(logger.info)
324+ def continue_(self):
325+ autopilot.input.Keyboard.create().press_and_release('Enter')
326+ return get_wizard(self).get_wifi_connect_page()
329+class WifiConnectPage(UbuntuUIToolkitCustomProxyObjectBase):
330+ """Helper class to interact with the Wi-Fi network list page"""
333+ def validate_dbus_object(cls, path, state):
334+ name = introspection.get_classname_from_path(path)
336+ if state['objectName'][1] == 'wifiPage':
340+ def _get_network(self, ssid):
341+ return self.wait_select_single(
342+ 'Standard', objectName='accessPoint', text=ssid, visible='True')
344+ def _get_network_checkbox(self, ssid):
345+ return self._get_network(ssid).select_single(
346+ 'CheckBox', visible='True')
348+ def _get_notification(self, unity):
349+ logger.info('Waiting longer for notification object')
350+ with override_proxy_timeout(unity, 30):
351+ return unity.wait_select_single(
352+ Notification, objectName='notification1', visible='True')
354+ def _get_back_button(self):
355+ return self.wait_select_single(
356+ 'StackButton', text='Back', visible='True')
358+ def _get_skip_button(self):
359+ return self.wait_select_single(
360+ 'StackButton', text='Skip', visible='True')
362+ def _get_continue_button(self):
363+ return self.wait_select_single(
364+ 'StackButton', text='Continue', visible='True')
366+ def is_network_checked(self, ssid):
367+ return self._get_network_checkbox(ssid).get_properties()['checked']
369+ @autopilot.logging.log_action(logger.info)
370+ def select_network(self, unity, ssid):
371+ self.pointing_device.click_object(self._get_network_checkbox(ssid))
372+ return PasswordNotification(self._get_notification(unity))
374+ @autopilot.logging.log_action(logger.info)
376+ self.pointing_device.click_object(self._get_back_button())
377+ return get_wizard(self).get_password_page()
379+ @autopilot.logging.log_action(logger.info)
381+ self.pointing_device.click_object(self._get_skip_button())
382+ return get_wizard(self).get_reporting_page()
384+ @autopilot.logging.log_action(logger.info)
385+ def continue_(self):
386+ self.pointing_device.click_object(self._get_continue_button())
387+ return get_wizard(self).get_reporting_page()
390+class Notification(UbuntuUIToolkitCustomProxyObjectBase):
391+ """Base class for notification objects"""
395+class PasswordNotification(Notification):
396+ """Helper class to interact with the password entry notification"""
398+ def __init__(self, notification):
399+ self.notification = notification
401+ def _get_connect_button(self):
402+ return self.notification.wait_select_single(
403+ 'Button', text='Connect', objectName='notify_button0')
405+ def _get_cancel_buttoon(self):
406+ return self.notification.wait_select_single(
407+ 'Button', text='Cancel', objectName='notify_button1')
409+ def _get_text_field(self):
410+ return self.notification.wait_select_single('TextField')
412+ @autopilot.logging.log_action(logger.info)
413+ def enter_text(self, text):
414+ self._get_text_field().write(text)
416+ @autopilot.logging.log_action(logger.info)
418+ self.notification.pointing_device.click_object(
419+ self._get_connect_button())
421+ @autopilot.logging.log_action(logger.info)
423+ self.notification.pointing_device.click_object(
424+ self._get_cancel_buttoon())
427+class ReportingPage(UbuntuUIToolkitCustomProxyObjectBase):
428+ """Helper class to interact with the reporting page"""
431+ def validate_dbus_object(cls, path, state):
432+ name = introspection.get_classname_from_path(path)
434+ if state['objectName'][1] == 'reportingPage':
438+ def _get_continue_button(self):
439+ return self.select_single('StackButton', text='Continue')
441+ def _get_back_button(self):
442+ return self.select_single('StackButton', text='Back')
444+ @autopilot.logging.log_action(logger.info)
446+ self.pointing_device.click_object(self._get_back_button())
447+ return get_wizard(self).get_wifi_connect_page()
449+ @autopilot.logging.log_action(logger.info)
450+ def continue_(self):
451+ self.pointing_device.click_object(self._get_continue_button())
452+ return get_wizard(self).get_finished_page()
455+class FinishedPage(UbuntuUIToolkitCustomProxyObjectBase):
456+ """Helper class to interact with the finished page"""
459+ def validate_dbus_object(cls, path, state):
460+ name = introspection.get_classname_from_path(path)
462+ if state['objectName'][1] == 'finishedPage':
466+ def _get_finish_button(self):
467+ return self.wait_select_single(
468+ 'StackButton', text='Finish', visible='True')
470+ @autopilot.logging.log_action(logger.info)
472+ self.pointing_device.click_object(self._get_finish_button())
473+ self.wait_until_destroyed()