1

I am creating an automation script with Selenium Python to be able to create user accounts on a website my company uses. The program pulls all the users information from active directory and passes the information through selenium to create the account. If a duplicate account is created the website throws an error. When it does this I am wanting selenium to recognize the error and add a number to the end of the username if it does not throw an error I want it to ignore and continue. I am trying to do this with a IF ELSE statement. The problem I am running in to is the HTML element that holds the error is always visible with only a small change in the HTML when the error is initialized. I tried writing the XPATH to catch the change but keep getting a TimeoutException error. I have added all of the script below along with both HTML elements showing before the error is thrown and after the error is thrown. If you have any suggestions on a better way to handle the error that will be greatly appreciated as well.

HTML of Error before being thrown

<div class="error-section ng-hide" ng-show="hasErrors">
        <button class="close" ng-click="clearErrors()"></button>
        <p>Sorry, something unexpected happened. Please try again.</p>
        <ul class="nostyle">
            <!-- ngRepeat: error in errorMessages -->
        </ul>
    </div>

HTML of Error after being thrown

<div class="error-section" ng-show="hasErrors">
        <button class="close" ng-click="clearErrors()"></button>
        <p>Sorry, something unexpected happened. Please try again.</p>
        <ul class="nostyle">
            <!-- ngRepeat: error in errorMessages --><li ng-repeat="error in errorMessages" class="ng-binding ng-scope">Code: 102000890</li><!-- end ngRepeat: error in errorMessages --><li ng-repeat="error in errorMessages" class="ng-binding ng-scope">FaultCode: InvalidData</li><!-- end ngRepeat: error in errorMessages --><li ng-repeat="error in errorMessages" class="ng-binding ng-scope">Error: 102000890 - Login Id is already in use. Please create a different login Id.</li><!-- end ngRepeat: error in errorMessages --><li ng-repeat="error in errorMessages" class="ng-binding ng-scope">Details: </li><!-- end ngRepeat: error in errorMessages -->
        </ul>
    </div>

Full Script

import time
from hashlib import new
from multiprocessing.connection import wait
from select import select
from webbrowser import BaseBrowser, Chrome
from xml.etree.ElementPath import find

from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.ui import WebDriverWait

import ADTest

driver = webdriver.Chrome()
driver.get('https://power.dat.com')

# chrome_optinons = webdriver.ChromeOptions()
# chrome_optinons.add_argument('--headless')
# chrome_optinons.add_argument('window-size=1920x1080')

#setup wait 
wait = WebDriverWait(driver, 10)

username = driver.find_element(By.XPATH, '//*[@id="mat-input-1"]')
username.send_keys('')

password = driver.find_element(By.XPATH, '//*[@id="mat-input-0"]')
password.send_keys('')


loginbutton = driver.find_element(By.XPATH, '//*[@id="submit-button"]')
loginbutton.click()

(time.sleep(2))

profiledrop = driver.find_element(By.XPATH, '//*[@id="user-salutation"]')
profiledrop.click()

#store original window ID
windows_before = driver.current_window_handle

# #checks no other windows open
# assert len(driver.window_handles) == 1


Adminbutton = driver.find_element(By.CSS_SELECTOR, '#userPreferencesUl > li:nth-child(5) > a')
Adminbutton.click()


# driver.switch_to.window(driver.window_handles[1])

#Wait for new window Tab
WebDriverWait(driver, 10).until(EC.number_of_windows_to_be(2))

windows_after = driver.window_handles

new_window = [x for x in windows_after if x != windows_before][0]

driver.switch_to.window(new_window)

#Tells program to wait till new window confirmed 
WebDriverWait(driver,20).until(EC.title_is("Admin"))

(time.sleep(5))

WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.newUser.ng-scope[ng-if^='isTrustedAdmin'][ng-click^='onNewUser']"))).click()
#NewUsrBtn.click()

#User Name
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[@class='ng-pristine ng-untouched ng-invalid ng-invalid-required ng-valid-pattern ng-valid-maxlength' and @name='loginId']"))).send_keys("TQL" + ADTest.DatUsrName)
#UsrNM.send_keys('justin')


#<input ng-required="true" ng-readonly="!hasPriviledgeToEdit(user)" ng-model="user.loginId" ng-pattern="/^[a-zA-Z0-9_]+$/" name="loginId" maxlength="16" class="ng-valid-pattern ng-valid-maxlength ng-dirty ng-valid-parse ng-valid ng-valid-required ng-touched" required="required">
#Password 
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[@class='ng-pristine ng-untouched ng-invalid ng-invalid-required ng-valid-pattern ng-valid-maxlength' and @name='password']"))).send_keys("total2")


#Confirm Password
element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[@name='confirmPassword']")))
element.send_keys("total2")
#State
state = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//select[@class='ng-pristine ng-untouched ng-invalid ng-invalid-required' and @name='state']")))
selectState = Select(state)
selectState.select_by_value('string:' + ADTest.DATST)

#First Name
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[@class='ng-pristine ng-untouched ng-invalid ng-invalid-required ng-valid-maxlength' and @name='firstName']"))).send_keys(ADTest.FirstN)

#Last Name
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[@class='ng-pristine ng-untouched ng-invalid ng-invalid-required ng-valid-maxlength' and @name='lastName']"))).send_keys(ADTest.LastN)

#Workgroup ID
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[@class='ng-pristine ng-untouched ng-invalid ng-invalid-required ng-valid-maxlength' and @name='initials']"))).send_keys(ADTest.DATint)

#Phone Number 
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[@class='ng-pristine ng-untouched ng-invalid ng-invalid-required ng-valid-pattern ng-valid-maxlength' and @name='primaryPhone']"))).send_keys("8005803101")

#Extension
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[@class='ng-pristine ng-untouched ng-valid ng-valid-pattern ng-valid-maxlength' and @name='primaryExtension']"))).send_keys(ADTest.ext)

#Email
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[@class='ng-pristine ng-untouched ng-valid-email ng-invalid ng-invalid-required ng-valid-maxlength' and @name='email']"))).send_keys(ADTest.email)

#National Account: Combo Premium Pooling Subscription 
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//label[contains(text(),'National Account: Combo Premium Pooling Subscripti')]"))).click()

#National Account: Combo Premium Pooling Subscription 
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//label[normalize-space()='National Account: DAT Connexion Subscription']"))).click()

#National Account: Combo Premium Pooling Subscription 
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//label[normalize-space()='National Account: Power Broker Subscription']"))).click()

#Submit Button 
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[normalize-space()='Add User']"))).click()

if WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.XPATH, '//*[@class= "error-section" and @id="data"]/div[1]'))):
    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, '//*[@id="data"]/div[3]/table/tbody[1]/tr/td[1]/ng-form/fieldset[1]/input'))).send_keys("1")
    
    # WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, '//*[@id="data"]/div[3]/table/tbody[1]/tr/td[1]/ng-form/fieldset[1]/input'))).send_keys("1")
    # WebDriverWait(driver,20).until(EC.element_to_be_clickable(By.XPATH, '//*[@id="data"]/div[1]/button')).click()
else:
    WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.XPATH, '//*[@class= "error-section ng-hide" and @id="data"]/div[1]')))
DaHawg
  • 73
  • 5

2 Answers2

1

Instead of using presence_of_element_located expected condition you can use presence_of_all_elements_located so in case of no match found it will just return you an empty list interpreted by Python as a Boolean false. Also, seems you do not need to use WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.XPATH, '//*[@class= "error-section ng-hide" and @id="data"]/div[1]'))) in the else part since you already checked the existence of the error notification.
So, your code could be as following:

if WebDriverWait(driver, 20).until(EC.presence_of_all_elements_located((By.XPATH, '//div[@class= "error-section"]//p[contains(.,"Sorry, something unexpected happened. Please try again.")]'))):
    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, '//*[@id="data"]/div[3]/table/tbody[1]/tr/td[1]/ng-form/fieldset[1]/input'))).send_keys("1")
    
else:
    # Do what you need to do here

Also, most locators you are using here, like //input[@class='ng-pristine ng-untouched ng-invalid ng-invalid-required ng-valid-maxlength' and @name='lastName'] are bad and should be improved.

Prophet
  • 32,350
  • 22
  • 54
  • 79
  • Thank you Prophet! I will give that a shot. I had to use the class ng because they are all angular elements. Is there another way to get around this? – DaHawg Aug 09 '22 at 17:23
  • The locators should be short as possible, only information making this locator unique is relevant. All redundant details should be removed. Let me know if it helped. – Prophet Aug 09 '22 at 17:27
  • Thank you cleaned up the script some and it has helped it run smoother. If you have any other advice. I would love to hear it. Would you like if I posted a update of the script? – DaHawg Aug 10 '22 at 00:21
  • Did my answer resolved your initial question? – Prophet Aug 10 '22 at 06:51
  • Yes it did resolve my problem. The only issue I am having now Is that I am trying to run multiple if else statements and it gets hung up if it doesnt have to go through all of them. – DaHawg Aug 11 '22 at 01:28
  • If so please open a new question for that and let me know, I'll try to help there as well – Prophet Aug 11 '22 at 06:49
1

To handle the probable error message you can wrapup the click on the Close button within a try-except{} block inducing WebDriverWait for the element_to_be_clickable() and you can use either of the following locator strategies:

  • Using CSS_SELECTOR:

    try:
      WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.close[ng-click^='clearErrors']"))).click()
      print("Closed error message")
    except TimeoutException:
      print("No error message")
    
  • Using XPATH:

    try:
      WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[@class='close' and starts-with(@ng-click, 'clearErrors')]"))).click()
      print("Closed error message")
    except TimeoutException:
      print("No error message")
    
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352