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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
#
# Copyright (C) 2013
#
# Author: Daniel Chapman daniel@chapman-mail.com
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation; version 3.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import random
import time
from autopilot.input import Pointer, Mouse, Keyboard
from ubiquity_autopilot_tests.emulators import AutopilotGtkEmulatorBase
from ubiquity_autopilot_tests.tools.compare import expectThat
import logging
logger = logging.getLogger(__name__)


class GtkContainers(AutopilotGtkEmulatorBase):
    """ Base class for all gtkcontainers objects """
    def __init__(self, *args):
        super(GtkContainers, self).__init__(*args)
        self.pointing_device = Pointer(Mouse.create())


class GtkBox(GtkContainers):
    """ Emulator class for a GtkBox instance """
    def __init__(self, *args):
        super(GtkBox, self).__init__(*args)
        self.pointing_device = Pointer(Mouse.create())
        self.kbd = Keyboard.create()

    def get_random_language(self, ):
        """ gets a random language from the 'stepLanguage' page

        :returns: A random TreeView item from the language treeview
        :raises: EmulatorException if function is not called from the
                step language page object

        You can now use select_language_item

        """
        logger.debug("get_random_language()")
        if self.name == 'stepLanguage':
            language_item = self._get_install_language()
            if language_item is None:
                raise ValueError("Language could not be selected")
            return language_item
        raise RuntimeError("Function can only be used from a stepLanguage "
                           "page object. Use .select_single('GtkBox, "
                           "name='stepLanguage')")

    def select_language(self, item):
        """ Selects a language for the install

        You can either use get_random_language or if you want to set the
        install language instead of randomly selecting an item. Then select
        from the treeview using GtkTreeView.select_item and pass the returned
        item to select_language

        :param item: A treeview item object
        :raises: exception if function not called from stepLanguage page object


        """
        if self.name == 'stepLanguage':
            logger.debug("select_language()")
            treeview = self.select_single('GtkTreeView')
            treeview.click()
            # for sanity lets ensure we always start at the top of the list
            tree_items = treeview.get_all_items()
            logger.debug("Selecting top item of treeview list")

            # Workaround LP:1619790
            # Press Up multiple time to go to the first item instead of Home
            for _ in tree_items:
                self.kbd.press_and_release('Up')
            top_item = tree_items[0]
            # If we are at the top
            if top_item.selected:
                logger.debug("top item {0} selected"
                             .format(top_item.accessible_name))
                # Now select required Language
                self.kbd.type(item.accessible_name[0:3])
                item.click()
                # check selected
                if item.selected:
                    logger.debug("Install language successfully selected! :-)")
                    return
                raise ValueError("Could not select Item")
            raise ValueError("Top item  not selected")
        raise ValueError("Function can only be used from a stepLanguage page "
                         "object. Use .select_single('GtkBox, "
                         "name='stepLanguage')")

    def _get_install_language(self, ):
        """ Gets a random language for the install

        :returns: an object of a TreeView item for the chosen language
        """
        logger.debug("_get_install_language()")
        treeview = self.select_single('GtkTreeView')
        # lets get all items
        treeview_items = treeview.get_all_items()

        # get a language which the first two chars can be ascii decoded
        test_language = self._get_decode_ascii_item(treeview_items)
        return test_language

    def _get_decode_ascii_item(self, items):
        """ decodes a list of unicode items """
        logger.debug("_get_decode_ascii_item()")
        # at the moment we can't select all locales as this would be a pain
        # to figure out all encodings for keyboard input
        lang_item = None
        l_ascii = None
        while True:
            lang_item = random.choice(items)
            l_unicode = lang_item.accessible_name
            logger.debug("Attempting to decode %s" % l_unicode)
            lan = l_unicode[0:2]
            try:
                l_ascii = lan.encode('ascii')
            except UnicodeEncodeError:
                logger.debug("%s could not be decoded" % l_unicode)
                pass
            if l_ascii:
                logger.debug("%s decoded successfully" % l_unicode)
                break
        logger.debug("Returning selected language: %s" % l_unicode)
        return lang_item

    def select_location(self, location):
        """ Selects a location on the timezone map """
        if self.name == 'stepLocation':
            logger.debug("select_location({0})".format(location))

            location_map = self.select_single('CcTimezoneMap')
            self.pointing_device.move_to_object(location_map)
            x1, y1, x2, y2 = location_map.globalRect
            # hmmmm this is tricky! and really hacky
            pos = self.pointing_device.position()
            x = pos[0]
            y = pos[1]
            x -= 25  # px
            self.pointing_device.move(x, y)
            while True:
                entry = self.select_single('GtkEntry')
                if entry.text != location:
                    pos = self.pointing_device.position()
                    x = pos[0]
                    y = pos[1]
                    y -= 10  # px
                    self.pointing_device.move(x, y)
                    self.pointing_device.click()
                    if y < y1:
                        logger.warning("We missed the location on the map and "
                                       "ended up outside the globalRect. Now "
                                       "using the default selected location "
                                       "instead")
                        break
                else:
                    expectThat(entry.text).equals(location)
                    logger.debug("Location; '{0}' selected".format(location))
                    break
        else:
            raise ValueError("Function can only be called from a "
                             "stepLocation page object")

    def create_user(self, name, password):
        """ Creates a user account with password

        :param name: Username
        :param password: user password

        """
        logger.debug("create_user({0}, {1})".format(name, password))
        if self.name == 'stepUserInfo':
            self._enter_username(name)
            self._enter_password(password)
        else:
            raise ValueError("Function can only be called froma stepUserInfo"
                             "page object")

    def _enter_username(self, name):
        """ Enters the username

        :param name: username for user account
        """
        logger.debug("_enter_username({0})".format(name))
        entry = self.select_single('GtkEntry', name='fullname')
        with self.kbd.focused_type(entry) as kb:
            kb.press_and_release('Ctrl+a')
            kb.press_and_release('Delete')
            kb.type(name)

        # lets get the fullname from the entry
        # as we don't know the kb layout till runtime
        fullname = entry.text
        logger.debug("Checking that name, username and hostname all contain "
                     "'{0}'".format(name))
        # now check computer name contains username
        hostname_entry = self.select_single('GtkEntry', name='hostname')
        expectThat(hostname_entry.text).contains(
            fullname.lower(),
            msg="GtkBox._enter_username(): Expected the hostname entry: "
                "'{0}', to contain '{1}'"
                .format(hostname_entry.text, fullname.lower()))
        # check username contains name
        username_entry = self.select_single('GtkEntry', name='username')
        expectThat(username_entry.text).contains(
            fullname.lower(),
            msg="GtkBox._enter_username(): Expected the username entry: "
                "'{0}', to contain '{1}'"
                .format(username_entry.text, fullname.lower()))
        # check the GtkYes images are now visible
        logger.debug("Checking the stock 'gtk-yes' images are visible")
        images = ['fullname_ok', 'hostname_ok', 'username_ok']
        for image in images:
            img = self.select_single('GtkImage', name=image)
            expectThat(img.visible).equals(
                True,
                msg="Expected {0} image to be visible but it wasn't"
                .format(img.name))
            expectThat(img.stock).equals(
                'gtk-yes',
                msg="Expected {0} image to have a 'gtk-yes' stock image and "
                    "not {1}".format(img.name, img.stock))

    def _enter_password(self, password):
        if self.name == 'stepUserInfo':

            while True:
                self._enter_pass_phrase(password)
                match = self._check_phrase_match()

                if match:
                    break
        else:
            raise ValueError("enter_crypto_phrase() can only be called from "
                             "stepPartCrypto page object")

    def _enter_pass_phrase(self, phrase):

        pwd_entries = ['password', 'verified_password']
        for i in pwd_entries:
            entry = self.select_single(BuilderName=i)
            with self.kbd.focused_type(entry) as kb:
                kb.press_and_release('Ctrl+a')
                kb.press_and_release('Delete')
                expectThat(entry.text).equals(
                    u'',
                    msg='{0} entry text was not cleared properly'
                    .format(entry.name))
                kb.type(phrase)

    def _check_phrase_match(self, ):
        pwd1 = self.select_single(BuilderName='password').text
        pwd2 = self.select_single(BuilderName='verified_password').text
        if pwd1 == pwd2:
            return True
        else:
            return False

    def encrypt_home_dir(self, encrypt=None):
        """ Check the login_encrypt box """
        chk_encrypt = self.select_single(BuilderName='login_encrypt')
        active = chk_encrypt.active

        if encrypt is None:
            # Switch checkbox and ensure it switched
            self.pointing_device.click_object(chk_encrypt)
            expectThat(chk_encrypt.active).equals(
                not active,
                msg='encrypt home checkbox state did not change. Current '
                'state: {0}'.format(chk_encrypt.active))
        elif encrypt and not active:
            self.pointing_device.click_object(chk_encrypt)
            expectThat(chk_encrypt.active).equals(
                True,
                msg='encrypt home checkbox not active and should be.')
        elif not encrypt and active:
            self.pointing_device.click_object(chk_encrypt)
            expectThat(chk_encrypt.active).equals(
                False,
                msg='encrypt home checkbox active and should not be.')
        else:
            raise ValueError("Invalid value for 'encrypt' parameter: {}"
                             .format(encrypt))


class GtkAlignment(GtkContainers):
    """ Emulator class for a GtkAlignment instance """
    def __init__(self, *args):
        super(GtkAlignment, self).__init__(*args)
        self.pointing_device = Pointer(Mouse.create())
        self.kbd = Keyboard.create()

    def enter_crypto_phrase(self, crypto_phrase):
        if self.name == 'stepPartCrypto':

            while True:
                self._enter_pass_phrase(crypto_phrase)
                match = self._check_crypto_phrase_match()

                if match:
                    break
        else:
            raise ValueError("enter_crypto_phrase() can only be called from "
                             "stepPartCrypto page object")

    def _enter_pass_phrase(self, phrase):

        pwd_entries = ['password', 'verified_password']
        for i in pwd_entries:
            entry = self.select_single(BuilderName=i)
            with self.kbd.focused_type(entry) as kb:
                kb.press_and_release('Ctrl+a')
                kb.press_and_release('Delete')
                expectThat(entry.text).equals(
                    u'',
                    msg='{0} entry text was not cleared properly'
                        .format(entry.name))
                kb.type(phrase)

    def _check_crypto_phrase_match(self, ):
        pwd1 = self.select_single(BuilderName='password').text
        pwd2 = self.select_single(BuilderName='verified_password').text
        if pwd1 == pwd2:
            return True
        else:
            return False

    def create_new_partition_table(self, ):
        if self.name == 'stepPartAdvanced':
            new_partition_button = self.select_single(
                BuilderName='partition_button_new_label')
            self.pointing_device.click_object(new_partition_button)
            time.sleep(5)
            self.kbd.press_and_release('Right')
            self.kbd.press_and_release('Enter')
            time.sleep(5)
        else:
            raise ValueError("create_new_partition_table() can only be called "
                             "from stepPartAdvanced page object")