From 985d8ec1a0e94905a05f1cea609ac297e43b3653 Mon Sep 17 00:00:00 2001 From: Aviadp Date: Mon, 23 Dec 2024 17:24:53 +0200 Subject: [PATCH] Create Tests of: create bucket via OBC create bucket via s3 upload folder and file to bucket Signed-off-by: Aviadp --- ocs_ci/ocs/ui/base_ui.py | 1 + ocs_ci/ocs/ui/page_objects/buckets_tab.py | 132 +++++++++++++++++- ocs_ci/ocs/ui/views.py | 57 +++++++- tests/functional/object/mcg/ui/test_mcg_ui.py | 13 ++ 4 files changed, 200 insertions(+), 3 deletions(-) diff --git a/ocs_ci/ocs/ui/base_ui.py b/ocs_ci/ocs/ui/base_ui.py index 34bd11704d2..20010f8fd8d 100644 --- a/ocs_ci/ocs/ui/base_ui.py +++ b/ocs_ci/ocs/ui/base_ui.py @@ -149,6 +149,7 @@ def __init__(self): self.topology_loc = self.deep_get(locators, self.ocp_version, "topology") self.storage_clients_loc = self.deep_get(locators, self.ocp_version, "storage") self.alerting_loc = self.deep_get(locators, self.ocp_version, "alerting") + self.bucket_tab = self.deep_get(locators, self.ocp_version, "bucket_tab") def __repr__(self): return f"{self.__class__.__name__} Web Page" diff --git a/ocs_ci/ocs/ui/page_objects/buckets_tab.py b/ocs_ci/ocs/ui/page_objects/buckets_tab.py index 3eb36f888c3..d7b1ccbe3b3 100644 --- a/ocs_ci/ocs/ui/page_objects/buckets_tab.py +++ b/ocs_ci/ocs/ui/page_objects/buckets_tab.py @@ -1,18 +1,146 @@ import json - +import logging +import uuid import requests +import random +import string +import os +import time + from selenium.webdriver.common.by import By +from selenium.common.exceptions import NoSuchElementException + from ocs_ci.ocs.ocp import get_ocp_url from ocs_ci.ocs import exceptions from ocs_ci.ocs.ui.page_objects.confirm_dialog import ConfirmDialog -from ocs_ci.ocs.ui.page_objects.object_storage import ObjectStorage, logger +from ocs_ci.ocs.ui.page_objects.object_storage import ObjectStorage from ocs_ci.utility import version +logger = logging.getLogger(__name__) + class BucketsTab(ObjectStorage, ConfirmDialog): + """ + A class representation for abstraction of Buckets tab related OpenShift UI actions + """ + def __init__(self): super().__init__() + # Methods can directly access locators via self.bucket_tab, self.generic_locators etc. + # No need to explicitly import or assign them + + def generate_folder_with_file(self): + # TODO: move to utils + """ + Generates a random folder with a random text file inside it in /tmp folder + + Returns: + str: Full path to the generated folder + """ + folder_name = "".join( + random.choices(string.ascii_lowercase + string.digits, k=8) + ) + folder_path = os.path.join("/tmp", folder_name) + os.makedirs(folder_path, exist_ok=True) + + filename = ( + "".join(random.choices(string.ascii_lowercase + string.digits, k=8)) + + ".txt" + ) + filepath = os.path.join(folder_path, filename) + + content = "".join( + random.choices(string.ascii_letters + string.digits + " \n", k=100) + ) + + with open(filepath, "w") as f: + f.write(content) + + return folder_path + + def create_bucket_ui(self, method): + + self.do_click(self.bucket_tab["create_bucket_button"]) + if method == "obc": + self.create_bucket_via_obc() + elif method == "s3": + self.create_bucket_via_s3() + else: + raise ValueError(f"Invalid method: {method}") + + def create_bucket_via_obc(self): + + self.do_click(self.bucket_tab["create_bucket_button_obc"]) + self.do_click(self.bucket_tab["storage_class_dropdown"]) + self.do_click(self.bucket_tab["storage_class_noobaa_option"]) + self.do_click(self.bucket_tab["submit_button_obc"]) + + def create_bucket_via_s3(self): + name_generator = f"test-bucket-s3-{uuid.uuid4()}" + + self.do_click(self.bucket_tab["create_bucket_button_s3"]) + self.do_send_keys(self.bucket_tab["bucket_name_input"], name_generator) + self.do_click(self.bucket_tab["submit_button_obc"]) + + def create_folder_in_bucket(self, bucket_name=None, folder_name=None): + # Note That object must be uploaded to the folder before navigating out of the bucket, + # else the folder will be vanished + + if bucket_name: + self.do_click(f"//tr//a[contains(text(), '{bucket_name}')]", By.XPATH) + else: + self.do_click(self.bucket_tab["first_bucket"]) + + if not folder_name: + folder_name = f"test-folder-{uuid.uuid4()}" + + self.do_click(self.bucket_tab["create_folder_button"]) + self.do_send_keys(self.bucket_tab["folder_name_input"], folder_name) + self.do_click(self.bucket_tab["submit_button_folder"]) + + folder_path = self.generate_folder_with_file() + + time.sleep(2) # Wait for folder navigation + + logger.info("=== DEBUG: STARTING FILE UPLOAD ===") + + try: + # Find the hidden file input + file_input = self.driver.find_element( + By.XPATH, "//input[@type='file'][@webkitdirectory]" + ) + logger.info("Found directory input") + + # Make the input visible and remove directory requirement + self.driver.execute_script( + """ + arguments[0].removeAttribute('webkitdirectory'); + arguments[0].removeAttribute('directory'); + arguments[0].style.display = 'block'; + arguments[0].style.visibility = 'visible'; + arguments[0].style.height = '1px'; + arguments[0].style.width = '1px'; + arguments[0].style.opacity = '1'; + """, + file_input, + ) + logger.info("Modified file input for direct interaction") + + file_path = os.path.join(folder_path, os.listdir(folder_path)[0]) + logger.info(f"Sending file path: {file_path}") + + file_input.send_keys(file_path) + logger.info("Successfully sent file path") + return folder_name + + except NoSuchElementException as e: + logger.error(f"Error during file upload: {str(e)}") + raise + + def check_folder_details(self, folder_name): + pass + def delete_bucket_ui(self, delete_via, expect_fail, resource_name): """ Delete an Object Bucket via the UI diff --git a/ocs_ci/ocs/ui/views.py b/ocs_ci/ocs/ui/views.py index 87aab0c4cc2..73d1572cba0 100644 --- a/ocs_ci/ocs/ui/views.py +++ b/ocs_ci/ocs/ui/views.py @@ -1989,7 +1989,61 @@ "alerting_rule_details_link": ("//a[normalize-space()='{}']", By.XPATH), } - +bucket_tab = { + "create_bucket_button_obc": ( + "//*[@id='content-scrollable']/section/div[2]/div[1]/div/div[2]/div[1]/div[2]", + By.XPATH, + ), + "storage_class_dropdown": ( + "[data-test='sc-dropdown']", + By.CSS_SELECTOR, + ), + "storage_class_noobaa_option": ( + "div.pf-v5-c-dropdown div:nth-of-type(2)", + By.CSS_SELECTOR, + ), + "create_bucket_button_s3": ( + "div:nth-of-type(2) > div.pf-v5-c-tile__body", + By.CSS_SELECTOR, + ), + "bucket_name_input": ( + "[data-test='bucket-name']", + By.CSS_SELECTOR, + ), + "submit_button_obc": ( + "[data-test='obc-create']", + By.CSS_SELECTOR, + ), + "first_bucket": ( + "tr:nth-of-type(1) a", + By.CSS_SELECTOR, + ), + "create_folder_button": ( + "div.pf-v5-u-w-50 > div > button.pf-v5-c-button", + By.CSS_SELECTOR, + ), + "folder_name_input": ( + "#folder-name", + By.CSS_SELECTOR, + ), + "submit_button_folder": ( + "button.pf-m-primary", + By.CSS_SELECTOR, + ), + "upload_button": ( + "//button[contains(text(), 'Upload')]", + By.XPATH, + ), + "file_input": ( + "input[multiple][type='file'][webkitdirectory]", + By.CSS_SELECTOR, + ), + "upload_submit": ( + "//button[text()='Upload']", + By.XPATH, + ), + "create_bucket_button": ("//*[@id='yaml-create']", By.XPATH), +} locators = { "4.18": { "login": {**login, **login_4_11, **login_4_14}, @@ -2042,6 +2096,7 @@ "topology": topology, "mcg_stores": mcg_stores, "alerting": alerting, + "bucket_tab": bucket_tab, }, "4.17": { "login": {**login, **login_4_11, **login_4_14}, diff --git a/tests/functional/object/mcg/ui/test_mcg_ui.py b/tests/functional/object/mcg/ui/test_mcg_ui.py index 267afc6efb8..b603ed1b06e 100644 --- a/tests/functional/object/mcg/ui/test_mcg_ui.py +++ b/tests/functional/object/mcg/ui/test_mcg_ui.py @@ -414,3 +414,16 @@ def test_obc_creation_and_deletion( obc_ui_obj.delete_obc_ui(obc_name, delete_via) assert test_obc.check_resource_existence(should_exist=False) + + +class TestBucketCreate: + def test_bucket_create(self, setup_ui_class_factory): + setup_ui_class_factory() + PageNavigator().nav_object_storage_page() + bucket_ui = BucketsTab() + bucket_ui.create_bucket_ui("obc") + PageNavigator().nav_object_storage_page() + bucket_ui.create_bucket_ui("s3") + PageNavigator().nav_object_storage_page() + bucket_ui.create_folder_in_bucket() + PageNavigator().nav_object_storage_page()