Home | History | Annotate | Download | only in files_CopyFileToGoogleDriveUI
      1 # Copyright 2018 The Chromium OS Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 import logging
      6 import os
      7 import time
      8 
      9 from commands import *
     10 
     11 from autotest_lib.client.common_lib import error
     12 from autotest_lib.client.common_lib.cros import chromedriver
     13 from selenium.webdriver.common.keys import Keys
     14 from autotest_lib.client.cros.graphics import graphics_utils
     15 from selenium.webdriver.common.action_chains import ActionChains
     16 from selenium.common.exceptions import WebDriverException
     17 
     18 TIMEOUT_TO_COPY = 1800  # in Secs. This timeout is for files beyond 1GB
     19 SEARCH_BUTTON_ID = "search-button"
     20 SEARCH_BOX_CSS = "div#search-box"
     21 PAPER_CONTAINTER = "paper-input-container"
     22 DELETE_BUTTON_ID = "delete-button"
     23 FILE_LIST_ID = "file-list"
     24 LABLE_ENTRY_CSS = "span.label.entry-name"
     25 CR_DIALOG_CLASS = "cr-dialog-ok"
     26 USER_LOCATION = "/home/chronos/user"
     27 # Using graphics_utils to simulate below keys
     28 OPEN_FILES_APPLICATION_KEYS = ["KEY_RIGHTSHIFT", "KEY_LEFTALT", "KEY_M"]
     29 SWITCH_TO_APP_KEY_COMBINATION = ["KEY_LEFTALT", 'KEY_TAB']
     30 SELECT_ALL_KEY_COMBINATION = ["KEY_LEFTCTRL", "KEY_A"]
     31 PASTE_KEY_COMBINATION = ["KEY_LEFTCTRL", "KEY_V"]
     32 GOOGLE_DRIVE = 'My Drive'
     33 
     34 
     35 class files_CopyFileToGoogleDriveUI(graphics_utils.GraphicsTest):
     36 
     37     """Copy a file from Downloads folder to Google drive"""
     38 
     39     version = 1
     40     TIME_DELAY = 5
     41     _WAIT_TO_LOAD = 5
     42 
     43     def initialize(self):
     44         """Autotest initialize function"""
     45         super(files_CopyFileToGoogleDriveUI, self).initialize(
     46                 raise_error_on_hang=True)
     47 
     48     def cleanup(self):
     49         """Autotest cleanup function"""
     50         if self._GSC:
     51             keyvals = self._GSC.get_memory_difference_keyvals()
     52             for key, val in keyvals.iteritems():
     53                 self.output_perf_value(
     54                     description=key,
     55                     value=val,
     56                     units='bytes',
     57                     higher_is_better=False)
     58             self.write_perf_keyval(keyvals)
     59         super(files_CopyFileToGoogleDriveUI, self).cleanup()
     60         # If test fails then script will collect the screen shot to know at
     61         # which instance failure occurred.
     62         if not self.success:
     63             graphics_utils.take_screenshot(os.path.join(self.debugdir),
     64                                            "chrome")
     65 
     66     def switch_to_app(self, driver, title):
     67         """Switching to application using title
     68 
     69         @param driver: chrome driver object
     70         @param title: Title of the application
     71         @return: True if the app is detected otherwise False
     72         """
     73         windows = driver.window_handles
     74         logging.debug("Windows opened: %s", windows)
     75         # Checking current window initially..
     76         logging.debug("Current window is %s", driver.title)
     77         if driver.title.strip().lower() == title.lower():
     78             return True
     79         # Switching to all opened windows to find out the required window
     80         for window in windows:
     81             try:
     82                 logging.debug("Switching to window")
     83                 driver.switch_to_window(window)
     84                 logging.debug("Switched to window: %s", driver.title)
     85                 time.sleep(2)
     86                 if driver.title.strip().lower() == title.lower():
     87                     logging.info("%s application opened!", title)
     88                     return True
     89             except WebDriverException as we:
     90                 logging.debug("Webdriver exception occurred. Exception: %s",
     91                               str(we))
     92             except Exception as e:
     93                 logging.debug("Exception: %s", str(e))
     94         return False
     95 
     96     def open_files_application(self, driver):
     97         """Open and switch to files application using graphics_utils.py
     98 
     99         @param driver: chrome driver object
    100         """
    101         logging.info("Opening files application")
    102         graphics_utils.press_keys(OPEN_FILES_APPLICATION_KEYS)
    103         time.sleep(self._WAIT_TO_LOAD)
    104         try:
    105             self.switch_to_files(driver)
    106         except Exception as e:
    107             logging.error("Exception when switching files application.. %s",
    108                           str(e))
    109             logging.error("Failed to find files application. Trying again.")
    110             graphics_utils.press_keys(OPEN_FILES_APPLICATION_KEYS)
    111             time.sleep(self._WAIT_TO_LOAD)
    112             self.switch_to_files(driver)
    113 
    114     def switch_to_files(self, driver, title="Downloads"):
    115         """Switch to files application
    116 
    117         @param driver: chrome driver object
    118         @param title: Title of the Files application
    119         """
    120         logging.debug("Switching/Focus on the Files app")
    121         if self.switch_to_app(driver, title):
    122             logging.info("Focused on Files application")
    123             graphics_utils.press_keys(SWITCH_TO_APP_KEY_COMBINATION)
    124             time.sleep(1)
    125         else:
    126             raise error.TestFail("Failed to open on Files application")
    127 
    128     def check_folder_opened(self, driver, title):
    129         """Check the selected folder is opened or not
    130 
    131         @param driver: chrome driver object
    132         @param title: Folder name
    133         @return: Returns True if expected folder is opened otherwise False
    134         """
    135         logging.info("Actual files application title is %s", driver.title)
    136         logging.info("Expected files application title is %s", title)
    137         if driver.title == title:
    138             return True
    139         return False
    140 
    141     def open_folder(self, driver, folder):
    142         """Open given folder
    143 
    144         @param driver: chrome driver object
    145         @param folder: Directory name
    146         """
    147         folder_webelements = driver.find_elements_by_css_selector(
    148             LABLE_ENTRY_CSS)
    149         for element in folder_webelements:
    150             try:
    151                 logging.debug("Found folder name: %s", element.text.strip())
    152                 if folder == element.text.strip():
    153                     element.click()
    154                     time.sleep(3)
    155                     if self.check_folder_opened(driver, element.text.strip()):
    156                         logging.info("Folder is opened!")
    157                         return
    158             except Exception as e:
    159                 logging.error("Exception when getting Files application "
    160                               "folders %s", str(e))
    161         raise error.TestError("Folder :%s is not opened or found", folder)
    162 
    163     def list_files(self, driver):
    164         """List files in the folder
    165 
    166         @param driver: chrome driver object
    167         @return: Returns list of files
    168         """
    169         return driver.find_element_by_id(
    170             FILE_LIST_ID).find_elements_by_tag_name('li')
    171 
    172     def search_file(self, driver, file_name):
    173         """Search given file in Files application
    174 
    175         @param driver: chrome driver object
    176         @param file_name: Required file
    177         """
    178         driver.find_element_by_id(SEARCH_BUTTON_ID).click()
    179         search_box_element = driver.find_element_by_css_selector(
    180             SEARCH_BOX_CSS)
    181         search_box_element.find_element_by_css_selector(
    182             PAPER_CONTAINTER).find_element_by_tag_name('input').clear()
    183         search_box_element.find_element_by_css_selector(
    184             PAPER_CONTAINTER).find_element_by_tag_name('input').send_keys(
    185             file_name)
    186 
    187     def copy_file(self, driver, source, destination, file_name, clean=True):
    188         """Copy file from one directory to another
    189 
    190         @param driver: chrome driver object
    191         @param source: Directory name from where to copy
    192         @param destination: Directory name to where to copy
    193         @param file_name: File to copy
    194         @param clean: Cleans destination if True otherwise nothing
    195         """
    196         self.open_folder(driver, source)
    197         self.search_file(driver, file_name)
    198         files = self.list_files(driver)
    199         action_chains = ActionChains(driver)
    200 
    201         for item in files:
    202             logging.info("Selecting file to copy in %s", file_name)
    203             item.click()
    204             file_size = item.text.split()[1].strip()
    205             file_size_units = item.text.split()[2].strip()
    206             logging.debug("Select copy")
    207             action_chains.move_to_element(item) \
    208                 .click(item).key_down(Keys.CONTROL) \
    209                 .send_keys("c") \
    210                 .key_up(Keys.CONTROL) \
    211                 .perform()
    212             self.open_folder(driver, destination)
    213             if clean:
    214                 drive_files = self.list_files(driver)
    215                 if len(drive_files) != 0:
    216                     logging.info("Removing existing files from %s",
    217                                  destination)
    218                     drive_files[0].click()
    219                     logging.debug("Select all files/dirs")
    220                     graphics_utils.press_keys(SELECT_ALL_KEY_COMBINATION)
    221                     time.sleep(0.2)
    222                     driver.find_element_by_id(DELETE_BUTTON_ID).click()
    223                     driver.find_element_by_class_name(CR_DIALOG_CLASS).click()
    224                     time.sleep(self.TIME_DELAY)
    225             logging.debug("Pressing control+v to paste the file in required "
    226                           "location")
    227             graphics_utils.press_keys(PASTE_KEY_COMBINATION)
    228             time.sleep(self.TIME_DELAY)
    229             # Take dummy values initially
    230             required_file_size = "0"
    231             required_file_size_units = "KB"
    232             required_file = None
    233             # wait till the data copied
    234             start_time = time.time()
    235             while required_file_size != file_size and \
    236                 required_file_size_units != file_size_units and \
    237                     (time.time() - start_time <= TIMEOUT_TO_COPY):
    238                 drive_files_during_copy = self.list_files(driver)
    239                 if len(drive_files_during_copy) == 0:
    240                     raise error.TestError("File copy not started!")
    241                 for i_item in drive_files_during_copy:
    242                     if i_item.text.strip().split()[0].strip() == file_name:
    243                         logging.info("File found %s", i_item.text.split()[
    244                             0].strip())
    245                         required_file = file
    246                 if not required_file:
    247                     raise error.TestError("No such file/directory in drive, "
    248                                           "%s", required_file)
    249                 logging.info(required_file.text.split())
    250                 required_file_size = required_file.text.split()[1]
    251                 required_file_size_units = required_file.text.split()[2]
    252                 time.sleep(5)
    253                 logging.debug("%s %s data copied" % (required_file_size,
    254                                                      required_file_size_units))
    255             # Validation starts here
    256             found = False
    257             drive_files_after_copy = self.list_files(driver)
    258             for copied_file in drive_files_after_copy:
    259                 logging.debug("File in destination: %s",
    260                               copied_file.text.strip())
    261                 if copied_file.find_element_by_class_name(
    262                         'entry-name').text.strip() == file_name:
    263                     found = True
    264                     break
    265 
    266             if found:
    267                 logging.info("Copied the file successfully!")
    268             else:
    269                 raise error.TestFail("File not transferred successfully!")
    270 
    271     def catch_info_or_error_messages(self, driver):
    272         """Logic to catch the error
    273 
    274         @param driver: chrome driver object
    275         """
    276         errors = []
    277         try:
    278             driver.find_element_by_css_selector(
    279                 'div.button-frame').find_element_by_class_name('open').click()
    280         except Exception as e:
    281             logging.info("Error in open error messages")
    282             logging.info(str(e))
    283         error_elements = driver.find_elements_by_css_selector(
    284             'div.progress-frame')
    285         if len(error_elements) != 0:
    286             for error_element in error_elements:
    287                 info_text = error_element.find_element_by_tag_name(
    288                     'label').text
    289                 if info_text != "":
    290                     errors.append(info_text)
    291         return errors
    292 
    293     def create_file(self, filename):
    294         """Create a file"""
    295         status, output = getstatusoutput('dd if=/dev/zero of=%s bs=%s '
    296                                          'count=1 iflag=fullblock' %
    297                                          (filename, 1024))
    298         if status:
    299             raise error.TestError("Failed to create file")
    300 
    301     def run_once(self, username=None, password=None, source="Downloads",
    302                  file_name='test.dat'):
    303         """Copy file to Google Drive in Files application
    304 
    305         @param username: Real user(Not default autotest user)
    306         @param password: Password for the user.
    307         @param source: From where to copy file
    308         @param file_name: File name
    309         """
    310         self.success = False  # Used to capture the screenshot if the TC fails
    311         with chromedriver.chromedriver(username=username,
    312                                        password=password,
    313                                        disable_default_apps=False,
    314                                        gaia_login=True) as cr_instance:
    315             driver = cr_instance.driver
    316             self.open_files_application(driver)
    317             self.create_file(os.path.join(os.path.join(USER_LOCATION,
    318                                                        source), file_name))
    319             self.copy_file(driver, source, GOOGLE_DRIVE, file_name)
    320             errors = self.catch_info_or_error_messages(driver)
    321             if len(errors):
    322                 raise error.TestFail("Test failed with the following"
    323                                      " errors. %s", errors)
    324         self.success = True
    325