0

I am using Selenium to automate a task.

The manual task requires someone to send bulk invoices. There are two sections:

  1. Invoices Queued for Print Delivery
  2. Invoices Queued for Email Delivery

Sectio 2 (Invoices Queued for Email Delivery) can be sent in bulk but Section 1 (Invoices Queued for Print Delivery) need to be sent individually by clicking Email button.

Once this Email button is clicked for Section 1, a pop up window will appear and a Send Invoice button needs to be clicked and then the pop up window will close once the invoice is sent.

Section 1 does not appear all the time. So when there is no email for Section 1, this section is not visible. And the number of email for this section varies.

I previously encountered StaleElementReferenceException error and have managed to avoid it by fetching fresh elements of the main page.

The issue that I am having right now is that, if Section 1 has 5 emails, I can't figure out how or where in my script that I should do this for loop so that it will click Send Invoice in the pop up window and go back to the main window, fetch fresh element and go back to the pop up window ...

This is my code:

### Do email run - Invoices Queued for Email Delivery ###

# Select the last table (Email delivery) and find the first checkbox and click 
tables = driver.find_elements_by_class_name('fsmall')
tables[-1].find_element_by_css_selector("td:nth-child(1)").click()

# Click Do email run button
driver.find_element_by_name("email_queue").click()

# Wait for 50 seconds
time.sleep(50)

# Get page again once DOM loaded
driver.get(url)

# Find Invoices Queued for Print Delivery Section
tables = driver.find_elements_by_class_name('fsmall')

if 'Invoices Queued for Print Delivery' in [item.text for item in tables]:

    ### First loop
    # Get table index of print delivery section 
    print_delivery_ind = [item.text for item in tables].index('Invoices Queued for Print Delivery')

    # Get the table after Print Delivery table
    idvdl_inv_tbl = tables[print_delivery_ind + 1]

    # Get name of main window
    main_window = driver.window_handles[0]

    # Find the first invoice and click Email
    idvdl_inv_tbl.find_element_by_link_text('Email').click()

    # Wait for 3 seconds
    time.sleep(3)

    # Get name of the pop up window
    popup_window = driver.window_handles[1]

    # Switch to the pop up window
    driver.switch_to_window(popup_window)

    # Find the Send Invoice button and click
    driver.find_element_by_name("submit_email").click()

    # Switch to the main window
    driver.switch_to_window(main_window)

    ### Second loop
    # Get page again once DOM loaded
    driver.get(url)

    # Get all tables
    tables = driver.find_elements_by_class_name('fsmall')

    # Get table index of Print Delivery section 
    print_delivery_ind = [item.text for item in tables].index('Invoices Queued for Print Delivery')

    # Get the table after Print Delivery table
    idvdl_inv_tbl = tables[print_delivery_ind + 1]

    # Get name of main window
    main_window = driver.window_handles[0]

    # Find the first invoice and click Email
    idvdl_inv_tbl.find_element_by_link_text('Email').click()

    # Wait for 3 seconds
    time.sleep(3)

    # Get name of the pop up window
    popup_window = driver.window_handles[1]

    # Switch to the pop up window
    driver.switch_to_window(popup_window)

    # Find the Send Invoice button and click
    driver.find_element_by_name("submit_email").click()

driver.close()

Would appreciate if someone can point me to the right direction. Thank you.

azmirfakkri
  • 571
  • 1
  • 6
  • 18
  • Is the code in the `if` section an attempt to do 2 loops over the items in Print Delivery? I'm asking because there is this comment, "Get table index of Email Delivery", but the next five line also gets the "Invoices Queued for Print Delivery" table - the comment contradicts the code? Also, right now you don't see StaleElementReferenceException, right, you just want to construct a more solid looping? – Todor Minakov Feb 08 '19 at 08:11
  • @TodorMinakov apologies I have edited my code there. The if section is an attempt to identify if Print Delivery section is available or not. Exactly, I don't see the error but I would like a more solid looping to make these codes more robust. Thank you. – azmirfakkri Feb 08 '19 at 08:27
  • 1
    Oh boy. @DebanjanB, please do not just close questions by glimpsing over the title and seeing a keyword of yours - in this case, StaleElementReferenceException. This question **does not have anything to do with StaleElementReferenceException**, OP is doing a lot of (pretty interesting) stuff **just not to hit it**. Now if you please, revert your mark as duplicate. I have an answer that is half a page long, won't do in the comments. – Todor Minakov Feb 08 '19 at 08:38

1 Answers1

1

Well there's a surprisingly small change that will make your loop iterate as long as there is "Invoices Queued for Print Delivery" in the tables. Change this line:

if 'Invoices Queued for Print Delivery' in [item.text for item in tables]:

to:

while 'Invoices Queued for Print Delivery' in [item.text for item in tables]:

Then inside the body of the loop, remove the 2nd element gather - while keeping the page reload, and the re-initialization of tables. So these lines:

### First loop
# Get table index of print delivery section 
print_delivery_ind = [item.text for item in tables].index('Invoices Queued for Print Delivery')

# -----
# the rest of the lines 
# -----

# up until these - keep them, and nothing afterwards:
# Get page again once DOM loaded
driver.get(url)

# Get all tables
tables = driver.find_elements_by_class_name('fsmall')

And thus you'll loop while there is the table with that text on the page.

Todor Minakov
  • 19,097
  • 3
  • 55
  • 60
  • 1
    Thanks @TodorMinakov I will test this code on Monday! Funny enough I had a similar script with while loop but my head didn't even think about while loop this time :D – azmirfakkri Feb 08 '19 at 15:25