1
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
5
# Author: Daniel Chapman daniel@chapman-mail.com
7
# This program is free software; you can redistribute it and/or modify it under
8
# the terms of the GNU Lesser General Public License as published by the Free
9
# Software Foundation; version 3.
11
# This program is distributed in the hope that it will be useful, but WITHOUT
12
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
16
# You should have received a copy of the GNU Lesser General Public License
17
# along with this program. If not, see <http://www.gnu.org/licenses/>.
20
from autopilot.input import Pointer, Mouse, Keyboard
21
from ubiquity_autopilot_tests.emulators import AutopilotGtkEmulatorBase
22
from ubiquity_autopilot_tests.tools.compare import expectThat
24
logger = logging.getLogger(__name__)
27
class GtkContainers(AutopilotGtkEmulatorBase):
28
""" Base class for all gtkcontainers objects """
29
def __init__(self, *args):
30
super(GtkContainers, self).__init__(*args)
31
self.pointing_device = Pointer(Mouse.create())
34
class GtkBox(GtkContainers):
35
""" Emulator class for a GtkBox instance """
36
def __init__(self, *args):
37
super(GtkBox, self).__init__(*args)
38
self.pointing_device = Pointer(Mouse.create())
39
self.kbd = Keyboard.create()
41
def get_random_language(self, ):
42
""" gets a random language from the 'stepLanguage' page
44
:returns: A random TreeView item from the language treeview
45
:raises: EmulatorException if function is not called from the
46
step language page object
48
You can now use select_language_item
51
logger.debug("get_random_language()")
52
if self.name == 'stepLanguage':
53
language_item = self._get_install_language()
54
if language_item is None:
55
raise ValueError("Language could not be selected")
57
raise RuntimeError("Function can only be used from a stepLanguage "
58
"page object. Use .select_single('GtkBox, "
59
"name='stepLanguage')")
61
def select_language(self, item):
62
""" Selects a language for the install
64
You can either use get_random_language or if you want to set the
65
install language instead of randomly selecting an item. Then select
66
from the treeview using GtkTreeView.select_item and pass the returned
67
item to select_language
69
:param item: A treeview item object
70
:raises: exception if function not called from stepLanguage page object
74
if self.name == 'stepLanguage':
75
logger.debug("select_language()")
76
treeview = self.select_single('GtkTreeView')
78
# for sanity lets ensure we always start at the top of the list
79
tree_items = treeview.get_all_items()
80
logger.debug("Selecting top item of treeview list")
82
# Workaround LP:1619790
83
# Press Up multiple time to go to the first item instead of Home
85
self.kbd.press_and_release('Up')
86
top_item = tree_items[0]
87
# If we are at the top
89
logger.debug("top item {0} selected"
90
.format(top_item.accessible_name))
91
# Now select required Language
92
self.kbd.type(item.accessible_name[0:3])
96
logger.debug("Install language successfully selected! :-)")
98
raise ValueError("Could not select Item")
99
raise ValueError("Top item not selected")
100
raise ValueError("Function can only be used from a stepLanguage page "
101
"object. Use .select_single('GtkBox, "
102
"name='stepLanguage')")
104
def _get_install_language(self, ):
105
""" Gets a random language for the install
107
:returns: an object of a TreeView item for the chosen language
109
logger.debug("_get_install_language()")
110
treeview = self.select_single('GtkTreeView')
112
treeview_items = treeview.get_all_items()
114
# get a language which the first two chars can be ascii decoded
115
test_language = self._get_decode_ascii_item(treeview_items)
118
def _get_decode_ascii_item(self, items):
119
""" decodes a list of unicode items """
120
logger.debug("_get_decode_ascii_item()")
121
# at the moment we can't select all locales as this would be a pain
122
# to figure out all encodings for keyboard input
126
lang_item = random.choice(items)
127
l_unicode = lang_item.accessible_name
128
logger.debug("Attempting to decode %s" % l_unicode)
131
l_ascii = lan.encode('ascii')
132
except UnicodeEncodeError:
133
logger.debug("%s could not be decoded" % l_unicode)
136
logger.debug("%s decoded successfully" % l_unicode)
138
logger.debug("Returning selected language: %s" % l_unicode)
141
def select_location(self, location):
142
""" Selects a location on the timezone map """
143
if self.name == 'stepLocation':
144
logger.debug("select_location({0})".format(location))
146
location_map = self.select_single('CcTimezoneMap')
147
self.pointing_device.move_to_object(location_map)
148
x1, y1, x2, y2 = location_map.globalRect
149
# hmmmm this is tricky! and really hacky
150
pos = self.pointing_device.position()
154
self.pointing_device.move(x, y)
156
entry = self.select_single('GtkEntry')
157
if entry.text != location:
158
pos = self.pointing_device.position()
162
self.pointing_device.move(x, y)
163
self.pointing_device.click()
165
logger.warning("We missed the location on the map and "
166
"ended up outside the globalRect. Now "
167
"using the default selected location "
171
expectThat(entry.text).equals(location)
172
logger.debug("Location; '{0}' selected".format(location))
175
raise ValueError("Function can only be called from a "
176
"stepLocation page object")
178
def create_user(self, name, password):
179
""" Creates a user account with password
181
:param name: Username
182
:param password: user password
185
logger.debug("create_user({0}, {1})".format(name, password))
186
if self.name == 'stepUserInfo':
187
self._enter_username(name)
188
self._enter_password(password)
190
raise ValueError("Function can only be called froma stepUserInfo"
193
def _enter_username(self, name):
194
""" Enters the username
196
:param name: username for user account
198
logger.debug("_enter_username({0})".format(name))
199
entry = self.select_single('GtkEntry', name='fullname')
200
with self.kbd.focused_type(entry) as kb:
201
kb.press_and_release('Ctrl+a')
202
kb.press_and_release('Delete')
205
# lets get the fullname from the entry
206
# as we don't know the kb layout till runtime
207
fullname = entry.text
208
logger.debug("Checking that name, username and hostname all contain "
209
"'{0}'".format(name))
210
# now check computer name contains username
211
hostname_entry = self.select_single('GtkEntry', name='hostname')
212
expectThat(hostname_entry.text).contains(
214
msg="GtkBox._enter_username(): Expected the hostname entry: "
215
"'{0}', to contain '{1}'"
216
.format(hostname_entry.text, fullname.lower()))
217
# check username contains name
218
username_entry = self.select_single('GtkEntry', name='username')
219
expectThat(username_entry.text).contains(
221
msg="GtkBox._enter_username(): Expected the username entry: "
222
"'{0}', to contain '{1}'"
223
.format(username_entry.text, fullname.lower()))
224
# check the GtkYes images are now visible
225
logger.debug("Checking the stock 'gtk-yes' images are visible")
226
images = ['fullname_ok', 'hostname_ok', 'username_ok']
228
img = self.select_single('GtkImage', name=image)
229
expectThat(img.visible).equals(
231
msg="Expected {0} image to be visible but it wasn't"
233
expectThat(img.stock).equals(
235
msg="Expected {0} image to have a 'gtk-yes' stock image and "
236
"not {1}".format(img.name, img.stock))
238
def _enter_password(self, password):
239
if self.name == 'stepUserInfo':
242
self._enter_pass_phrase(password)
243
match = self._check_phrase_match()
248
raise ValueError("enter_crypto_phrase() can only be called from "
249
"stepPartCrypto page object")
251
def _enter_pass_phrase(self, phrase):
253
pwd_entries = ['password', 'verified_password']
254
for i in pwd_entries:
255
entry = self.select_single(BuilderName=i)
256
with self.kbd.focused_type(entry) as kb:
257
kb.press_and_release('Ctrl+a')
258
kb.press_and_release('Delete')
259
expectThat(entry.text).equals(
261
msg='{0} entry text was not cleared properly'
265
def _check_phrase_match(self, ):
266
pwd1 = self.select_single(BuilderName='password').text
267
pwd2 = self.select_single(BuilderName='verified_password').text
273
def encrypt_home_dir(self, encrypt=None):
274
""" Check the login_encrypt box """
275
chk_encrypt = self.select_single(BuilderName='login_encrypt')
276
active = chk_encrypt.active
279
# Switch checkbox and ensure it switched
280
self.pointing_device.click_object(chk_encrypt)
281
expectThat(chk_encrypt.active).equals(
283
msg='encrypt home checkbox state did not change. Current '
284
'state: {0}'.format(chk_encrypt.active))
285
elif encrypt and not active:
286
self.pointing_device.click_object(chk_encrypt)
287
expectThat(chk_encrypt.active).equals(
289
msg='encrypt home checkbox not active and should be.')
290
elif not encrypt and active:
291
self.pointing_device.click_object(chk_encrypt)
292
expectThat(chk_encrypt.active).equals(
294
msg='encrypt home checkbox active and should not be.')
296
raise ValueError("Invalid value for 'encrypt' parameter: {}"
300
class GtkAlignment(GtkContainers):
301
""" Emulator class for a GtkAlignment instance """
302
def __init__(self, *args):
303
super(GtkAlignment, self).__init__(*args)
304
self.pointing_device = Pointer(Mouse.create())
305
self.kbd = Keyboard.create()
307
def enter_crypto_phrase(self, crypto_phrase):
308
if self.name == 'stepPartCrypto':
311
self._enter_pass_phrase(crypto_phrase)
312
match = self._check_crypto_phrase_match()
317
raise ValueError("enter_crypto_phrase() can only be called from "
318
"stepPartCrypto page object")
320
def _enter_pass_phrase(self, phrase):
322
pwd_entries = ['password', 'verified_password']
323
for i in pwd_entries:
324
entry = self.select_single(BuilderName=i)
325
with self.kbd.focused_type(entry) as kb:
326
kb.press_and_release('Ctrl+a')
327
kb.press_and_release('Delete')
328
expectThat(entry.text).equals(
330
msg='{0} entry text was not cleared properly'
334
def _check_crypto_phrase_match(self, ):
335
pwd1 = self.select_single(BuilderName='password').text
336
pwd2 = self.select_single(BuilderName='verified_password').text
342
def create_new_partition_table(self, ):
343
if self.name == 'stepPartAdvanced':
344
new_partition_button = self.select_single(
345
BuilderName='partition_button_new_label')
346
self.pointing_device.click_object(new_partition_button)
348
self.kbd.press_and_release('Right')
349
self.kbd.press_and_release('Enter')
352
raise ValueError("create_new_partition_table() can only be called "
353
"from stepPartAdvanced page object")