From 24a112071fb7a2b73ae166884019797e0236ec83 Mon Sep 17 00:00:00 2001 From: Rokas Puzonas Date: Sun, 19 Dec 2021 00:12:07 +0200 Subject: [PATCH] fix: fix bug, when filename contains spaces --- action.yml | 4 +-- main.py | 100 ++++++++++++++++++++++++++++++++++------------------- 2 files changed, 67 insertions(+), 37 deletions(-) diff --git a/action.yml b/action.yml index 5aae880..8f60d77 100644 --- a/action.yml +++ b/action.yml @@ -22,7 +22,7 @@ runs: with: python-version: 3.x - name: Clone moodle uploader - run: git clone https://github.com/RokasPuzonas/ktu-moodle-assignment-upload -b v1.0.2 + run: git clone https://github.com/RokasPuzonas/ktu-moodle-assignment-upload -b v1.0.3 shell: "bash" - name: Setup Geckodriver uses: browser-actions/setup-geckodriver@v0.0.0 @@ -32,7 +32,7 @@ runs: python -m venv venv source venv/bin/activate pip install -r requirements.txt - ./main.py ${{ inputs.assignment-id }} ../${{ inputs.target-filename }} ${{ inputs.upload-filename }} + ./main.py ${{ inputs.assignment-id }} "../${{ inputs.target-filename }}" "${{ inputs.upload-filename }}" env: KTU_USERNAME: ${{ inputs.ktu-username }} KTU_PASSWORD: ${{ inputs.ktu-password }} diff --git a/main.py b/main.py index 08c1f89..6cc9a64 100755 --- a/main.py +++ b/main.py @@ -1,68 +1,98 @@ #!/usr/bin/env python from selenium import webdriver import click -from selenium.webdriver.firefox.options import Options -from selenium.webdriver.remote.webdriver import WebDriver -from selenium.common.exceptions import NoSuchElementException -from selenium.webdriver.common.by import By from dotenv import load_dotenv import time from os import path +from typing import Optional + +from selenium.webdriver.firefox.options import Options +from selenium.webdriver.remote.webdriver import WebDriver +from selenium.webdriver.remote.webelement import WebElement +from selenium.common.exceptions import NoSuchElementException, TimeoutException +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.common.by import By load_dotenv() LOGIN_URL = "https://moodle.ktu.edu/login/index.php" EDIT_ASSIGNMENT_URL = "https://moodle.ktu.edu/mod/assign/view.php?id={id}&action=editsubmission" +DEFAULT_TIMEOUT = 5 + def create_driver() -> WebDriver: options = Options() options.headless = True return webdriver.Firefox(options=options) -def login(driver: WebDriver, username, password): - driver.get(LOGIN_URL) - - driver.find_element(By.ID, "username").send_keys(username) - driver.find_element(By.ID, "password").send_keys(password) - driver.find_element(By.XPATH, "//input[@type='submit']").click() - time.sleep(1) - - driver.find_element(By.ID, "yesbutton").click() - time.sleep(1) - -def safe_find_element(driver, *args, **kvargs): +def waited_find_element( + driver: WebDriver, + by: str, + value: str, + timeout: int = DEFAULT_TIMEOUT + ) -> Optional[WebElement]: try: - return driver.find_element(*args, **kvargs) - except NoSuchElementException: + return WebDriverWait(driver, timeout).until(EC.presence_of_element_located((by, value))) + except TimeoutException: return None -def upload_file_to_assignment(driver: WebDriver, assignment, filename, upload_filename): +def waited_find_elements( + driver: WebDriver, + by: str, + value: str, + timeout: int = DEFAULT_TIMEOUT + ) -> list[WebElement]: + try: + return WebDriverWait(driver, timeout).until(EC.presence_of_all_elements_located((by, value))) + except TimeoutException: + return [] + +def assert_element( + error_msg: str, + driver: WebDriver, + by: str, + value: str, + timeout: int = DEFAULT_TIMEOUT + ) -> WebElement: + element = waited_find_element(driver, by, value, timeout) + if not element: + raise NoSuchElementException(error_msg) + return element + +def login(driver: WebDriver, username: str, password: str): + driver.get(LOGIN_URL) + + assert_element("Failed to select username field", driver, By.ID, "username").send_keys(username) + assert_element("Failed to select password field", driver, By.ID, "password").send_keys(password) + assert_element("Failed to select login submit button", driver, By.XPATH, "//input[@type='submit']").click() + + assert_element("Failed to select yes button in login", driver, By.ID, "yesbutton").click() + time.sleep(1) + +def upload_file_to_assignment(driver: WebDriver, assignment_id: str, filename: str, upload_filename: str): if not upload_filename: upload_filename = path.basename(filename) - driver.get(EDIT_ASSIGNMENT_URL.format(id=assignment)) - time.sleep(1) + driver.get(EDIT_ASSIGNMENT_URL.format(id=assignment_id)) - # Check if file exists - file = safe_find_element(driver, By.XPATH, f"//*[text()='{upload_filename}']") - if file: + # Check if files exists in assignment + for file_elem in waited_find_elements(driver, By.XPATH, "//*[contains(@class, 'fp-file')]/*[contains(@class, 'd-block')]"): # If it does, delete it - file.click() time.sleep(1) - driver.find_element(By.XPATH, "//button[text()='Naikinti']").click() - time.sleep(1) - driver.find_element(By.XPATH, "//button[contains(@class, 'fp-dlg-butconfirm')]").click() - time.sleep(1) - - driver.find_element(By.CLASS_NAME, "filemanager-container").click() + file_elem.click() + assert_element("Failed to press delete file button", driver, By.CLASS_NAME, "fp-file-delete").click() + assert_element("Failed to press confirm deletion file button", driver, By.CLASS_NAME, "fp-dlg-butconfirm").click() time.sleep(1) - driver.find_element(By.XPATH, "//input[@type='file']").send_keys(path.abspath(filename)) - driver.find_element(By.XPATH, "//input[@name='title']").send_keys(upload_filename) - driver.find_element(By.CLASS_NAME, "fp-upload-btn").click() + assert_element("Failed to click on file manager", driver, By.CLASS_NAME, "dndupload-arrow").click() + assert_element("Failed to select file upload from computer", driver, By.XPATH, "//*[contains(@class, 'fp-repo-area')]/*[contains(@class, 'fp-repo')][2]").click() + assert_element("Failed to specify upload file", driver, By.XPATH, "//input[@type='file']").send_keys(path.abspath(filename)) + assert_element("Failed to specify uploaded files name", driver, By.XPATH, "//input[@name='title']").send_keys(upload_filename) + assert_element("Failed to press upload file button", driver, By.CLASS_NAME, "fp-upload-btn").click() time.sleep(1) - driver.find_element(By.ID, "id_submitbutton").click() + assert_element("Failed to press submit files button", driver, By.ID, "id_submitbutton").click() @click.command() @click.argument("assignment")