~elementary-os/ubuntu-package-imports/ubiquity-bionic

« back to all changes in this revision

Viewing changes to autopilot/ubiquity_autopilot_tests/emulators/gtkcontainers.py

  • Committer: RabbitBot
  • Date: 2018-02-05 14:44:42 UTC
  • Revision ID: rabbitbot@elementary.io-20180205144442-vt0fvth7zus90wjh
Initial import, version 17.10.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
 
2
#
 
3
# Copyright (C) 2013
 
4
#
 
5
# Author: Daniel Chapman daniel@chapman-mail.com
 
6
#
 
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.
 
10
#
 
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
 
14
# details.
 
15
#
 
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/>.
 
18
import random
 
19
import time
 
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
 
23
import logging
 
24
logger = logging.getLogger(__name__)
 
25
 
 
26
 
 
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())
 
32
 
 
33
 
 
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()
 
40
 
 
41
    def get_random_language(self, ):
 
42
        """ gets a random language from the 'stepLanguage' page
 
43
 
 
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
 
47
 
 
48
        You can now use select_language_item
 
49
 
 
50
        """
 
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")
 
56
            return language_item
 
57
        raise RuntimeError("Function can only be used from a stepLanguage "
 
58
                           "page object. Use .select_single('GtkBox, "
 
59
                           "name='stepLanguage')")
 
60
 
 
61
    def select_language(self, item):
 
62
        """ Selects a language for the install
 
63
 
 
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
 
68
 
 
69
        :param item: A treeview item object
 
70
        :raises: exception if function not called from stepLanguage page object
 
71
 
 
72
 
 
73
        """
 
74
        if self.name == 'stepLanguage':
 
75
            logger.debug("select_language()")
 
76
            treeview = self.select_single('GtkTreeView')
 
77
            treeview.click()
 
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")
 
81
 
 
82
            # Workaround LP:1619790
 
83
            # Press Up multiple time to go to the first item instead of Home
 
84
            for _ in tree_items:
 
85
                self.kbd.press_and_release('Up')
 
86
            top_item = tree_items[0]
 
87
            # If we are at the top
 
88
            if top_item.selected:
 
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])
 
93
                item.click()
 
94
                # check selected
 
95
                if item.selected:
 
96
                    logger.debug("Install language successfully selected! :-)")
 
97
                    return
 
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')")
 
103
 
 
104
    def _get_install_language(self, ):
 
105
        """ Gets a random language for the install
 
106
 
 
107
        :returns: an object of a TreeView item for the chosen language
 
108
        """
 
109
        logger.debug("_get_install_language()")
 
110
        treeview = self.select_single('GtkTreeView')
 
111
        # lets get all items
 
112
        treeview_items = treeview.get_all_items()
 
113
 
 
114
        # get a language which the first two chars can be ascii decoded
 
115
        test_language = self._get_decode_ascii_item(treeview_items)
 
116
        return test_language
 
117
 
 
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
 
123
        lang_item = None
 
124
        l_ascii = None
 
125
        while True:
 
126
            lang_item = random.choice(items)
 
127
            l_unicode = lang_item.accessible_name
 
128
            logger.debug("Attempting to decode %s" % l_unicode)
 
129
            lan = l_unicode[0:2]
 
130
            try:
 
131
                l_ascii = lan.encode('ascii')
 
132
            except UnicodeEncodeError:
 
133
                logger.debug("%s could not be decoded" % l_unicode)
 
134
                pass
 
135
            if l_ascii:
 
136
                logger.debug("%s decoded successfully" % l_unicode)
 
137
                break
 
138
        logger.debug("Returning selected language: %s" % l_unicode)
 
139
        return lang_item
 
140
 
 
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))
 
145
 
 
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()
 
151
            x = pos[0]
 
152
            y = pos[1]
 
153
            x -= 25  # px
 
154
            self.pointing_device.move(x, y)
 
155
            while True:
 
156
                entry = self.select_single('GtkEntry')
 
157
                if entry.text != location:
 
158
                    pos = self.pointing_device.position()
 
159
                    x = pos[0]
 
160
                    y = pos[1]
 
161
                    y -= 10  # px
 
162
                    self.pointing_device.move(x, y)
 
163
                    self.pointing_device.click()
 
164
                    if y < y1:
 
165
                        logger.warning("We missed the location on the map and "
 
166
                                       "ended up outside the globalRect. Now "
 
167
                                       "using the default selected location "
 
168
                                       "instead")
 
169
                        break
 
170
                else:
 
171
                    expectThat(entry.text).equals(location)
 
172
                    logger.debug("Location; '{0}' selected".format(location))
 
173
                    break
 
174
        else:
 
175
            raise ValueError("Function can only be called from a "
 
176
                             "stepLocation page object")
 
177
 
 
178
    def create_user(self, name, password):
 
179
        """ Creates a user account with password
 
180
 
 
181
        :param name: Username
 
182
        :param password: user password
 
183
 
 
184
        """
 
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)
 
189
        else:
 
190
            raise ValueError("Function can only be called froma stepUserInfo"
 
191
                             "page object")
 
192
 
 
193
    def _enter_username(self, name):
 
194
        """ Enters the username
 
195
 
 
196
        :param name: username for user account
 
197
        """
 
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')
 
203
            kb.type(name)
 
204
 
 
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(
 
213
            fullname.lower(),
 
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(
 
220
            fullname.lower(),
 
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']
 
227
        for image in images:
 
228
            img = self.select_single('GtkImage', name=image)
 
229
            expectThat(img.visible).equals(
 
230
                True,
 
231
                msg="Expected {0} image to be visible but it wasn't"
 
232
                .format(img.name))
 
233
            expectThat(img.stock).equals(
 
234
                'gtk-yes',
 
235
                msg="Expected {0} image to have a 'gtk-yes' stock image and "
 
236
                    "not {1}".format(img.name, img.stock))
 
237
 
 
238
    def _enter_password(self, password):
 
239
        if self.name == 'stepUserInfo':
 
240
 
 
241
            while True:
 
242
                self._enter_pass_phrase(password)
 
243
                match = self._check_phrase_match()
 
244
 
 
245
                if match:
 
246
                    break
 
247
        else:
 
248
            raise ValueError("enter_crypto_phrase() can only be called from "
 
249
                             "stepPartCrypto page object")
 
250
 
 
251
    def _enter_pass_phrase(self, phrase):
 
252
 
 
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(
 
260
                    u'',
 
261
                    msg='{0} entry text was not cleared properly'
 
262
                    .format(entry.name))
 
263
                kb.type(phrase)
 
264
 
 
265
    def _check_phrase_match(self, ):
 
266
        pwd1 = self.select_single(BuilderName='password').text
 
267
        pwd2 = self.select_single(BuilderName='verified_password').text
 
268
        if pwd1 == pwd2:
 
269
            return True
 
270
        else:
 
271
            return False
 
272
 
 
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
 
277
 
 
278
        if encrypt is None:
 
279
            # Switch checkbox and ensure it switched
 
280
            self.pointing_device.click_object(chk_encrypt)
 
281
            expectThat(chk_encrypt.active).equals(
 
282
                not active,
 
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(
 
288
                True,
 
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(
 
293
                False,
 
294
                msg='encrypt home checkbox active and should not be.')
 
295
        else:
 
296
            raise ValueError("Invalid value for 'encrypt' parameter: {}"
 
297
                             .format(encrypt))
 
298
 
 
299
 
 
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()
 
306
 
 
307
    def enter_crypto_phrase(self, crypto_phrase):
 
308
        if self.name == 'stepPartCrypto':
 
309
 
 
310
            while True:
 
311
                self._enter_pass_phrase(crypto_phrase)
 
312
                match = self._check_crypto_phrase_match()
 
313
 
 
314
                if match:
 
315
                    break
 
316
        else:
 
317
            raise ValueError("enter_crypto_phrase() can only be called from "
 
318
                             "stepPartCrypto page object")
 
319
 
 
320
    def _enter_pass_phrase(self, phrase):
 
321
 
 
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(
 
329
                    u'',
 
330
                    msg='{0} entry text was not cleared properly'
 
331
                        .format(entry.name))
 
332
                kb.type(phrase)
 
333
 
 
334
    def _check_crypto_phrase_match(self, ):
 
335
        pwd1 = self.select_single(BuilderName='password').text
 
336
        pwd2 = self.select_single(BuilderName='verified_password').text
 
337
        if pwd1 == pwd2:
 
338
            return True
 
339
        else:
 
340
            return False
 
341
 
 
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)
 
347
            time.sleep(5)
 
348
            self.kbd.press_and_release('Right')
 
349
            self.kbd.press_and_release('Enter')
 
350
            time.sleep(5)
 
351
        else:
 
352
            raise ValueError("create_new_partition_table() can only be called "
 
353
                             "from stepPartAdvanced page object")