John K
John K

Reputation: 33

App with Selenium Not Responding - Not showing the progress bar and Not Emitting the text in Console until the task is completed

enter image description here

Window title is showing as Not Responding when using PyQt5 and selenium. The progress bar and the console emit stream displays after the completion of execution of script. Need help in getting this fixed.

 from selenium import webdriver
 from selenium.common.exceptions import 
  TimeoutException,NoSuchElementException,ElementClickInterceptedException
 from selenium.webdriver.support.ui import WebDriverWait,Select
 from selenium.webdriver.support import expected_conditions as EC
 from selenium.webdriver.common.by import By
 from selenium.webdriver.firefox.options import Options
 from selenium.webdriver.firefox.firefox_profile import FirefoxProfile
 from selenium.webdriver.common.action_chains import ActionChains
 import time
 import os.path
 import pandas as pd
 import csv
 import threading
 from PyQt5 import QtCore, QtGui, QtWidgets

 class EmittingStream(QtCore.QObject):

textWritten = QtCore.pyqtSignal(str)
def write(self, text):
    self.textWritten.emit(str(text))

 class Ui_Fuse(object):

def launch_Selenium_Thread(self):
    _translate = QtCore.QCoreApplication.translate
    self.pushButton.setEnabled(False)
    self.progressBar.setValue(0)
    self.textEdit.clear()
    t = threading.Thread(target=self.generate())
    t.start()

def loaddata(self):
    self.completed = 0
    while self.completed < 100:
        self.completed += 0.0001
        self.progressBar.setValue(self.completed)

def setupUi(self, Fuse):
    Fuse.setObjectName("Fuse")
    Fuse.resize(513, 284)
    font = QtGui.QFont()
    font.setPointSize(10)
    font.setBold(True)
    font.setWeight(75)
    Fuse.setFont(font)
    self.label = QtWidgets.QLabel(Fuse)
    self.label.setGeometry(QtCore.QRect(90, 67, 71, 20))
    self.label.setObjectName("label")
    self.LineEdit = QtWidgets.QLineEdit(Fuse)
    self.LineEdit.setGeometry(QtCore.QRect(170, 60, 181, 31))
    self.LineEdit.setObjectName("textEdit")
    self.LineEdit_2 = QtWidgets.QLineEdit(Fuse)
    self.LineEdit_2.setGeometry(QtCore.QRect(170, 100, 181, 31))
    self.LineEdit_2.setObjectName("textEdit_2")
    self.LineEdit_2.setEchoMode(QtWidgets.QLineEdit.Password)
    self.pushButton = QtWidgets.QPushButton(Fuse)
    self.pushButton.setGeometry(QtCore.QRect(169, 150, 90, 31))
    self.pushButton.setObjectName("pushButton")
    self.pushButton.clicked.connect(self.launch_Selenium_Thread)
    self.pushButton.clicked.connect(self.loaddata)
    self.pushButton_2 = QtWidgets.QPushButton(Fuse)
    self.pushButton_2.setGeometry(QtCore.QRect(262, 150, 90, 31))
    self.pushButton_2.setObjectName("pushButton_3")
    self.pushButton_2.clicked.connect(self.clearall)
    self.label_2 = QtWidgets.QLabel(Fuse)
    self.label_2.setGeometry(QtCore.QRect(89, 107, 71, 20))
    self.label_2.setObjectName("label_2")
    self.label_3 = QtWidgets.QLabel(Fuse)
    self.label_3.setGeometry(QtCore.QRect(180, 127, 181, 30))
    self.label_3.setObjectName("label_3")
    self.progressBar = QtWidgets.QProgressBar(Fuse)
    self.progressBar.setEnabled(True)
    self.progressBar.setGeometry(QtCore.QRect(8, 270, 506, 10))
    self.progressBar.setLayoutDirection(QtCore.Qt.LeftToRight)
    self.progressBar.setAutoFillBackground(False)
    self.progressBar.setProperty("value", 24)
    self.progressBar.setAlignment(QtCore.Qt.AlignJustify)
    self.progressBar.setInvertedAppearance(False)
    self.progressBar.setObjectName("progressBar")
    self.textEdit = QtWidgets.QTextEdit(Fuse)
    self.textEdit.setGeometry(QtCore.QRect(8, 200, 497, 60))
    self.textEdit.setObjectName("textEdit")
    self.textEdit.setFont(font)
    self.textEdit.setReadOnly(True)

    self.retranslateUi(Fuse)
    QtCore.QMetaObject.connectSlotsByName(Fuse)

def retranslateUi(self, Fuse):
    _translate = QtCore.QCoreApplication.translate
    Fuse.setWindowTitle(_translate("Fuse", "Fuse | Invoice Generation"))
    self.label.setText(_translate("Fuse", "<html><head/><body><p><span style=\" font-size:10pt; font-weight:600;\">User Name</span></p></body></html>"))
    self.pushButton.setText(_translate("Fuse", "Submit"))
    self.pushButton_2.setText(_translate("Fuse", "Reset"))
    self.label_2.setText(_translate("Fuse", "<html><head/><body><p><span style=\" font-size:10pt; font-weight:600;\">Password</span></p></body></html>"))
    self.label_3.setText(_translate("Fuse", "<html><head/><body><p><span style=\" font-size:7pt; color:red; font-weight:600;\">Invalid User Name or Password</span></p></body></html>"))
    self.label_3.hide()
    Fuse.setWindowFlags( QtCore.Qt.CustomizeWindowHint | QtCore.Qt.MSWindowsFixedSizeDialogHint |QtCore.Qt.WindowCloseButtonHint | QtCore.Qt.WindowMinimizeButtonHint )

def clearall(self):
    self.LineEdit.clear()
    self.LineEdit_2.clear()
    self.label_3.clear()
    self.textEdit.clear()
    self.LineEdit.setEnabled(True)
    self.LineEdit_2.setEnabled(True)
    self.pushButton.setEnabled(True)

def __init__(self, parent=None, **kwargs):
    sys.stdout = EmittingStream(textWritten=self.normalOutputWritten)
    sys.stderr = EmittingStream(textWritten=self.normalOutputWritten)

def __del__(self):
    sys.stdout = sys.__stdout__
    sys.stderr = sys.__stderr__

def normalOutputWritten(self, text):
    cursor = self.textEdit.textCursor()
    cursor.movePosition(QtGui.QTextCursor.End)
    cursor.insertText(text)
    self.textEdit.setTextCursor(cursor)
    self.textEdit.ensureCursorVisible()

def generate(self):
    self.LineEdit.setEnabled(False)
    self.LineEdit_2.setEnabled(False)
    self.pushButton.setEnabled(False)
    self.textEdit.clear()
    options = Options()
    options.add_argument("--headless")
    profile = FirefoxProfile()
    driver = webdriver.Firefox(firefox_profile=profile,firefox_options=options,executable_path= os.path.expandvars('%userprofile%\\Desktop\\RPA\\Tools\\geckodriver.exe'))
    driver.get("https://example.com/Login.aspx")
    try:
        WebDriverWait(driver, 60000).until(
        EC.element_to_be_clickable((By.ID, "loginBtnn")));
    except TimeoutException:
        self.textEdit.insertPlainText('Timed out waiting for page to load')
    search_field = driver.find_element_by_id("txtUserName")
    search_field.clear()
    username = self.LineEdit.text()
    search_field.send_keys(username)
    search_field = driver.find_element_by_id("txtPassword")
    search_field.clear()
    password = self.LineEdit_2.text()
    search_field.send_keys(password)
    time.sleep(5)
    driver.find_element_by_id("BtnLogin").click()
    self.textEdit.insertPlainText('Clicked on Login')
    time.sleep(5)
    try:
        element = driver.find_element_by_xpath("//span[contains(@id,'lblFailure')]")
        if element.text == "Invalid User Name or Password":
            self.textEdit.insertPlainText("Invalid User Name or Password")
            self.label_3.show()
            self.LineEdit.setEnabled(True)
            self.LineEdit_2.setEnabled(True)
            self.pushButton.setEnabled(True)
            driver.quit()
            driver.close()
    except NoSuchElementException:
        self.textEdit.insertPlainText("Correct User Name or Password")
    try:
        WebDriverWait(driver, 60000).until(
        EC.element_to_be_clickable((By.XPATH, "/html/body/form/div[4]/a/img")));
    except TimeoutException:
        self.textEdit.insertPlainText('Timed out waiting for page to load')    
    driver.find_element_by_xpath("/html/body/form/div[4]/a/img").click()
    self.textEdit.insertPlainText('Clicked Product Links')
    try:
        WebDriverWait(driver, 60000).until(
        EC.element_to_be_clickable((By.ID, "lnkFuse")));
    except TimeoutException:
        self.textEdit.insertPlainText('Timed out waiting for page to load')   
    driver.find_element_by_id("lnkFuse").click()
    self.textEdit.insertPlainText('Clicked on Fuse Link')
    try:
        WebDriverWait(driver, 60000).until(
        EC.element_to_be_clickable((By.XPATH, "//span[@class='Invoice Processing'][contains(.,'Invoice Processing')]")));
    except TimeoutException:
        self.textEdit.insertPlainText('Timed out waiting for page to load')
    element_to_hover_over = driver.find_element_by_xpath("//span[@class='Invoice Processing'][contains(.,'Invoice Processing')]")
    hover = ActionChains(driver).move_to_element(element_to_hover_over)
    hover.perform()
    self.textEdit.insertPlainText('Clicked on Invoice Processing')
    try:
        WebDriverWait(driver, 60000).until(
        EC.element_to_be_clickable((By.XPATH, "//a[@href='../../RS/Batch/AuditInvoice.aspx']")));
    except TimeoutException:
        self.textEdit.insertPlainText('Timed out waiting for page to load')
    driver.find_element_by_xpath("//a[@href='../../RS/Batch/AuditInvoice.aspx']").click()
    self.textEdit.insertPlainText('Clicked on Audit Invoices')
    try:
        WebDriverWait(driver, 60000).until(
        EC.element_to_be_clickable((By.ID, "MainContent_ddlSearchInvoiceStatus")));
    except TimeoutException:
        self.textEdit.insertPlainText('Timed out waiting for page to load')
    invoice_audit = 'Audited' 
    InvoiceStatus = Select(driver.find_element_by_id("MainContent_ddlSearchInvoiceStatus"))
    for option in InvoiceStatus.options:
        option_text = option.text
        if invoice_audit in option_text:
            option.click()
            break
    self.textEdit.insertPlainText('Selected Audited from Dropdown')
    try:
        WebDriverWait(driver, 60000).until(
        EC.element_to_be_clickable((By.ID, "MainContent_btnSearch")));
    except TimeoutException:
        self.textEdit.insertPlainText('Timed out waiting for page to load')
    driver.find_element_by_id('MainContent_btnSearch').click() 
    self.textEdit.insertPlainText('Clicked on Search Button')
    try:
        WebDriverWait(driver, 60000).until(
        EC.element_to_be_clickable((By.ID, "MainContent_ddlItemsPerPage")));
    except TimeoutException:
        self.textEdit.insertPlainText('Timed out waiting for page to load')    
    element = driver.find_element_by_id('MainContent_ddlItemsPerPage')
    element.location_once_scrolled_into_view
    driver.find_element_by_id('MainContent_ddlItemsPerPage').click() 
    items_perpage = '500' 
    records_list = Select(driver.find_element_by_id("MainContent_ddlItemsPerPage"))
    for option in records_list.options:
        option_text = option.text
        if items_perpage in option_text:
            option.click()
            break
    time.sleep(5)
    self.textEdit.insertPlainText('Selected Max items per page')

    list_links = driver.find_elements_by_partial_link_text('Generate')
    time.sleep(5)
    id_list = []
    for i in list_links:
        data = i.get_attribute('id')
        self.textEdit.insertPlainText(data)
        id_list.append(data)
        id_df = pd.DataFrame(id_list)
        self.textEdit.insertPlainText(id_df)
    for row in id_df.values:
        row_val = str(row)[2:-2]
        try:
            WebDriverWait(driver, 60000).until(
            EC.element_to_be_clickable((By.ID, "MainContent_gvAuditInvoice")));
            self.textEdit.insertPlainText('Element Found')               
            element = driver.find_element_by_id(row_val)
            element.location_once_scrolled_into_view
            WebDriverWait(driver, 60000).until(
            EC.element_to_be_clickable((By.ID, row_val)));
            driver.find_element_by_id(row_val).click()
            localtime = time.strftime("%m-%d-%Y  %I:%M:%S")
            self.textEdit.insertPlainText(row_val + "|" + 'Clicked' + '|' + localtime)
            time.sleep(5)
        except ElementClickInterceptedException:
            continue
            self.textEdit.insertPlainText('Timed out waiting for page to load')
        time.sleep(5)
    self.textEdit.insertPlainText('Completed')
    self.LineEdit.clear()
    self.LineEdit_2.clear()
    self.label_3.clear()
    self.LineEdit.setEnabled(True)
    self.LineEdit_2.setEnabled(True)
    self.pushButton.setEnabled(True)
    self.stop_Selenium_Thread()

def stop_Selenium_Thread(self):
    _translate = QtCore.QCoreApplication.translate
    self.pushButton.setEnabled(True)
    t = threading.Thread(target=self.stop_Selenium_Thread)
    for i, t in enumerate(self.generate()):
        t.join()
        print('Thread {} Stopped'.format(i))


if __name__ == "__main__":
   import sys
   app = QtWidgets.QApplication(sys.argv)
   Fuse = QtWidgets.QDialog()
   ui = Ui_Fuse()
   ui.setupUi(Fuse)
   Fuse.show()
   sys.exit(app.exec_())

My actual result should be when i hit the submit button on the app, the program should start executing the script and the self.textEdit.insertPlainText given in the code should stream in the text edit with progress bar moving.

Upvotes: 1

Views: 1156

Answers (1)

eyllanesc
eyllanesc

Reputation: 244132

Before all you have the following bad programming practices:

  • You're messing up the business logic with the GUI.
  • The names of the variables do not describe the use made of the variables.
  • A lot of code in a file.

On the other hand going to Qt you have the following errors:

  • You should not modify the GUI from another thread since the GUI is not tread-safe, you must use the signals, events, etc.
  • You must use layouts for the GUI to adapt when you change the size.

On the other hand I have not tested your code but I see that one of your errors is

t = threading.Thread(target=self.generate())

since you are invoking the function instead of passing it to the function, it must be

t = threading.Thread(target=self.generate)

Considering the above, I have implemented the following:

fuse_ui.py

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'fuse.ui'
#
# Created by: PyQt5 UI code generator 5.12.1
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_Fuse(object):
    def setupUi(self, Fuse):
        Fuse.setObjectName("Fuse")
        Fuse.resize(556, 513)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(Fuse.sizePolicy().hasHeightForWidth())
        Fuse.setSizePolicy(sizePolicy)
        self.verticalLayout = QtWidgets.QVBoxLayout(Fuse)
        self.verticalLayout.setObjectName("verticalLayout")
        spacerItem = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
        self.verticalLayout.addItem(spacerItem)
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        spacerItem1 = QtWidgets.QSpacerItem(80, 20, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_2.addItem(spacerItem1)
        self.gridLayout = QtWidgets.QGridLayout()
        self.gridLayout.setObjectName("gridLayout")
        self.userNameLabel = QtWidgets.QLabel(Fuse)
        self.userNameLabel.setObjectName("userNameLabel")
        self.gridLayout.addWidget(self.userNameLabel, 0, 0, 1, 1)
        self.userNameLineEdit = QtWidgets.QLineEdit(Fuse)
        self.userNameLineEdit.setObjectName("userNameLineEdit")
        self.gridLayout.addWidget(self.userNameLineEdit, 0, 1, 1, 1)
        self.passwordLabel = QtWidgets.QLabel(Fuse)
        self.passwordLabel.setObjectName("passwordLabel")
        self.gridLayout.addWidget(self.passwordLabel, 1, 0, 1, 1)
        self.passwordLineEdit = QtWidgets.QLineEdit(Fuse)
        self.passwordLineEdit.setObjectName("passwordLineEdit")
        self.gridLayout.addWidget(self.passwordLineEdit, 1, 1, 1, 1)
        self.invalidLabel = QtWidgets.QLabel(Fuse)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.invalidLabel.sizePolicy().hasHeightForWidth())
        self.invalidLabel.setSizePolicy(sizePolicy)
        self.invalidLabel.setAlignment(QtCore.Qt.AlignCenter)
        self.invalidLabel.setObjectName("invalidLabel")
        self.gridLayout.addWidget(self.invalidLabel, 2, 1, 1, 1)
        self.widget = QtWidgets.QWidget(Fuse)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.widget.sizePolicy().hasHeightForWidth())
        self.widget.setSizePolicy(sizePolicy)
        self.widget.setObjectName("widget")
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.widget)
        self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.submitButton = QtWidgets.QPushButton(self.widget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.submitButton.sizePolicy().hasHeightForWidth())
        self.submitButton.setSizePolicy(sizePolicy)
        self.submitButton.setObjectName("submitButton")
        self.horizontalLayout.addWidget(self.submitButton)
        self.resetButton = QtWidgets.QPushButton(self.widget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.resetButton.sizePolicy().hasHeightForWidth())
        self.resetButton.setSizePolicy(sizePolicy)
        self.resetButton.setObjectName("resetButton")
        self.horizontalLayout.addWidget(self.resetButton)
        self.gridLayout.addWidget(self.widget, 3, 1, 1, 1)
        self.horizontalLayout_2.addLayout(self.gridLayout)
        spacerItem2 = QtWidgets.QSpacerItem(80, 20, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_2.addItem(spacerItem2)
        self.verticalLayout.addLayout(self.horizontalLayout_2)
        spacerItem3 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
        self.verticalLayout.addItem(spacerItem3)
        self.logTextEdit = QtWidgets.QTextEdit(Fuse)
        self.logTextEdit.setObjectName("logTextEdit")
        self.verticalLayout.addWidget(self.logTextEdit)
        self.progressBar = QtWidgets.QProgressBar(Fuse)
        self.progressBar.setProperty("value", 24)
        self.progressBar.setObjectName("progressBar")
        self.verticalLayout.addWidget(self.progressBar)

        self.retranslateUi(Fuse)
        QtCore.QMetaObject.connectSlotsByName(Fuse)

    def retranslateUi(self, Fuse):
        _translate = QtCore.QCoreApplication.translate
        Fuse.setWindowTitle(_translate("Fuse", "Dialog"))
        self.userNameLabel.setText(_translate("Fuse", "<html><head/><body><p><span style=\" font-weight:600;\">User Name</span></p></body></html>"))
        self.passwordLabel.setText(_translate("Fuse", "<html><head/><body><p><span style=\" font-weight:600;\">Password</span></p></body></html>"))
        self.invalidLabel.setText(_translate("Fuse", "<html><head/><body><p><span style=\" font-size:7pt; color:red; font-weight:600;\">Invalid User Name or Password</span></p></body></html>"))
        self.submitButton.setText(_translate("Fuse", "Submit"))
        self.resetButton.setText(_translate("Fuse", "Reset"))




if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    Fuse = QtWidgets.QDialog()
    ui = Ui_Fuse()
    ui.setupUi(Fuse)
    Fuse.show()
    sys.exit(app.exec_())

fusi_worker.py

import os
import time

from selenium import webdriver
from selenium.common.exceptions import TimeoutException,NoSuchElementException,ElementClickInterceptedException
from selenium.webdriver.support.ui import WebDriverWait,Select
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.firefox.firefox_profile import FirefoxProfile
from selenium.webdriver.common.action_chains import ActionChains

from PyQt5 import QtCore

import pandas as pd

class FusiWorker(QtCore.QObject):
    progressChanged = QtCore.pyqtSignal(int)
    logSignal = QtCore.pyqtSignal(str)
    invalidSignal = QtCore.pyqtSignal()
    finished = QtCore.pyqtSignal()

    @QtCore.pyqtSlot(str, str)
    def start(self, username, password):

        options = Options()
        options.add_argument("--headless")
        profile = FirefoxProfile()
        driver_path = os.path.expandvars('%userprofile%\\Desktop\\RPA\\Tools\\geckodriver.exe')
        driver = webdriver.Firefox(firefox_profile=profile, options=options, executable_path=driver_path)
        driver.get("https://example.com/Login.aspx")
        try:
            WebDriverWait(driver, 60000).until(EC.element_to_be_clickable((By.ID, "loginBtnn")));
        except TimeoutException:
            self.logSignal.emit('Timed out waiting for page to load')

        search_field = driver.find_element_by_id("txtUserName")
        search_field.clear()
        search_field.send_keys(password)
        time.sleep(5)
        driver.find_element_by_id("BtnLogin").click()
        self.logSignal.emit('Clicked on Login')
        time.sleep(5)
        try:
            element = driver.find_element_by_xpath("//span[contains(@id,'lblFailure')]")
            if element.text == "Invalid User Name or Password":
                self.logSignal.emit("Invalid User Name or Password")
                self.invalidSignal.emit()
                driver.quit()
                driver.close()
        except NoSuchElementException:
            self.logSignal.emit("Correct User Name or Password")
        try:
            WebDriverWait(driver, 60000).until(EC.element_to_be_clickable((By.XPATH, "/html/body/form/div[4]/a/img")));
        except TimeoutException:
            self.logSignal.emit('Timed out waiting for page to load')    
        driver.find_element_by_xpath("/html/body/form/div[4]/a/img").click()
        self.logSignal('Clicked Product Links')
        try:
            WebDriverWait(driver, 60000).until(EC.element_to_be_clickable((By.ID, "lnkFuse")));
        except TimeoutException:
            self.logSignal.emit('Timed out waiting for page to load')
        driver.find_element_by_id("lnkFuse").click()
        self.logSignal.emit('Clicked on Fuse Link')
        try:
            WebDriverWait(driver, 60000).until(EC.element_to_be_clickable((By.XPATH, "//span[@class='Invoice Processing'][contains(.,'Invoice Processing')]")));
        except TimeoutException:
            self.logSignal.emit('Timed out waiting for page to load')
        element_to_hover_over = driver.find_element_by_xpath("//span[@class='Invoice Processing'][contains(.,'Invoice Processing')]")
        hover = ActionChains(driver).move_to_element(element_to_hover_over)
        hover.perform()
        self.logSignal.emit('Clicked on Invoice Processing')
        try:
            WebDriverWait(driver, 60000).until(EC.element_to_be_clickable((By.XPATH, "//a[@href='../../RS/Batch/AuditInvoice.aspx']")))
        except TimeoutException:
            self.logSignal.emit('Timed out waiting for page to load')
        driver.find_element_by_xpath("//a[@href='../../RS/Batch/AuditInvoice.aspx']").click()
        self.logSignal.emit('Clicked on Audit Invoices')
        try:
            WebDriverWait(driver, 60000).until(EC.element_to_be_clickable((By.ID, "MainContent_ddlSearchInvoiceStatus")))
        except TimeoutException:
            self.logSignal.emit('Timed out waiting for page to load')
        invoice_audit = 'Audited' 
        InvoiceStatus = Select(driver.find_element_by_id("MainContent_ddlSearchInvoiceStatus"))
        for option in InvoiceStatus.options:
            option_text = option.text
            if invoice_audit in option_text:
                option.click()
                break
        self.logSignal.emit('Selected Audited from Dropdown')
        try:
            WebDriverWait(driver, 60000).until(EC.element_to_be_clickable((By.ID, "MainContent_btnSearch")))
        except TimeoutException:
            self.logSignal.emit('Timed out waiting for page to load')
        driver.find_element_by_id('MainContent_btnSearch').click() 
        self.logSignal.emit('Clicked on Search Button')
        try:
            WebDriverWait(driver, 60000).until(EC.element_to_be_clickable((By.ID, "MainContent_ddlItemsPerPage")))
        except TimeoutException:
            self.logSignal.emit('Timed out waiting for page to load')
        element = driver.find_element_by_id('MainContent_ddlItemsPerPage')
        element.location_once_scrolled_into_view
        driver.find_element_by_id('MainContent_ddlItemsPerPage').click() 
        items_perpage = '500' 
        records_list = Select(driver.find_element_by_id("MainContent_ddlItemsPerPage"))
        for option in records_list.options:
            option_text = option.text
            if items_perpage in option_text:
                option.click()
                break
        time.sleep(5)
        self.logSignal.emit('Selected Max items per page')
        list_links = driver.find_elements_by_partial_link_text('Generate')
        time.sleep(5)
        id_list = []
        for i in list_links:
            data = i.get_attribute('id')
            self.logSignal.emit(data)
            id_list.append(data)
            # TODO
            id_df = pd.DataFrame(id_list)
            self.logSignal.emit(id_df.to_string())
        for row in id_df.values:
            row_val = str(row)[2:-2]
            try:
                WebDriverWait(driver, 60000).until(EC.element_to_be_clickable((By.ID, "MainContent_gvAuditInvoice")))
                self.logSignal.emit('Element Found')
                element = driver.find_element_by_id(row_val)
                element.location_once_scrolled_into_view
                WebDriverWait(driver, 60000).until(EC.element_to_be_clickable((By.ID, row_val)))
                driver.find_element_by_id(row_val).click()
                localtime = time.strftime("%m-%d-%Y  %I:%M:%S")
                self.logSignal.emit(row_val + "|" + 'Clicked' + '|' + localtime)
                time.sleep(5)
            except ElementClickInterceptedException:
                continue
                self.logSignal.emit('Timed out waiting for page to load')
            time.sleep(5)
        self.logSignal.emit('Completed')
        self.finished.emit()

    @QtCore.pyqtSlot()
    def load_data(self):
        completed = 0
        while completed < 100:
            completed += 0.0001
            self.progressChanged.emit(completed)
            time.sleep(0.01)

main.py

import threading
from PyQt5 import QtCore, QtGui, QtWidgets

from fuse_worker import FusiWorker
from fuse_ui import Ui_Fuse

class Fuse(QtWidgets.QDialog, Ui_Fuse):
    def __init__(self, parent=None):
        super(Fuse, self).__init__(parent)
        self.setupUi(self)
        self.setWindowFlags(QtCore.Qt.CustomizeWindowHint | 
                             QtCore.Qt.MSWindowsFixedSizeDialogHint |
                             QtCore.Qt.WindowCloseButtonHint | 
                             QtCore.Qt.WindowMinimizeButtonHint)
        self.init()
        self.connections()

    def init(self):
        self._worker = FusiWorker()
        self.reset()
        thread = QtCore.QThread(self)
        thread.start()
        self._worker.moveToThread(thread)
        self.progressBar.setValue(0)

    def connections(self):
        self.submitButton.clicked.connect(self.submit)
        self.resetButton.clicked.connect(self.reset)
        self._worker.logSignal.connect(self.logTextEdit.insertPlainText)
        self._worker.invalidSignal.connect(self.invalidate)
        self._worker.finished.connect(self.reset)
        self._worker.progressChanged.connect(self.progressBar.setValue)
        self.progressBar.setValue(0)

    @QtCore.pyqtSlot()
    def submit(self):
        username = self.userNameLineEdit.text()
        password = self.passwordLineEdit.text()
        self.logTextEdit.clear()
        self.userNameLineEdit.setEnabled(False)
        self.passwordLineEdit.setEnabled(False)
        threading.Thread(target=self._worker.start, args=(username, password,), daemon=True).start()
        threading.Thread(target=self._worker.load_data, daemon=True).start()

    @QtCore.pyqtSlot()
    def reset(self):
         self.userNameLineEdit.clear()
         self.passwordLineEdit.clear()
         self.invalidLabel.hide()
         self.userNameLineEdit.setEnabled(True)
         self.passwordLineEdit.setEnabled(True)
         self.submitButton.setEnabled(True)

    @QtCore.pyqtSlot()
    def invalidate(self):
        self.invalidLabel.show()
        self.reset()

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = Fuse()
    w.show()
    sys.exit(app.exec_())

These files must be in the same folder:

├── fuse_ui.py
├── fuse_worker.py
└── main.py

Upvotes: 2

Related Questions