Home > database >  Python selenium - presence_of_all_elements_located not working
Python selenium - presence_of_all_elements_located not working

Time:10-24

I just wrote this simple test in which it submits the form and tried to find values in the todo app. But it not working. I'm using WebDriverWait to wait until the page loads after form submission. But it is not waiting for the page to load and I don't know why.

Please help me out, what is wrong with this code?

import unittest
from unittest import TestCase
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


class NewUserTest(TestCase):
    """
    Test for a new user actions 
    """

    def setUp(self):
        self.browser = webdriver.Firefox()
        self.browser.implicitly_wait(10)

    def tearDown(self):
        self.browser.quit()

    def check_row_in_table(self, rowItem):
        rows = WebDriverWait(self.browser, 30).until(
            EC.presence_of_all_elements_located(
                (By.CSS_SELECTOR, '#todo-items-table tr')
            )
        )

        self.assertIn(
            rowItem,
            [row.text for row in rows]
        )

    def test_starting_a_new_todo_list(self):
        """
        Test for when a user creates a new todo list
        """

        # Check title
        self.browser.get('http://localhost:8000')
        self.assertIn('To-Do', self.browser.title)

        # check header text - h1
        header = self.browser.find_element(By.TAG_NAME, 'h1')
        self.assertEqual(header.text, 'To-Do List')

        # check inputbox for new to-do
        inputbox = self.browser.find_element(By.ID, 'todo-item')
        self.assertEqual(inputbox.get_attribute(
            'placeholder'), 'Enter a to-do item')

        # add 2 new item to to-do list
        inputbox.send_keys("Go to gym")
        inputbox.send_keys(Keys.ENTER)

        self.check_row_in_table('1. Go to gym')

        # inputbox = self.browser.find_element(By.ID, 'todo-item')
        # inputbox.send_keys("Prepare breakfast")
        # inputbox.send_keys(Keys.ENTER)

        # self.check_row_in_table('1. Go to gym')
        # self.check_row_in_table('2. Prepare breakfast')


if __name__ == '__main__':
    unittest.main()

It shows me the following error.

➜ python functional_test.py
E
======================================================================
ERROR: test_starting_a_new_todo_list (__main__.NewUserTest)
Test for when a user creates a new todo list
----------------------------------------------------------------------
Traceback (most recent call last):
  File "functional_test.py", line 53, in test_starting_a_new_todo_list
    self.check_row_in_table('1. Go to gym')
  File "functional_test.py", line 28, in check_row_in_table
    [row.text for row in rows]
  File "functional_test.py", line 28, in <listcomp>
    [row.text for row in rows]
  File "/home/pkkulhari/.virtualenvs/todo/lib/python3.8/site-packages/selenium/webdriver/remote/webelement.py", line 76, in text
    return self._execute(Command.GET_ELEMENT_TEXT)['value']
  File "/home/pkkulhari/.virtualenvs/todo/lib/python3.8/site-packages/selenium/webdriver/remote/webelement.py", line 693, in _execute
    return self._parent.execute(command, params)
  File "/home/pkkulhari/.virtualenvs/todo/lib/python3.8/site-packages/selenium/webdriver/remote/webdriver.py", line 418, in execute
    self.error_handler.check_response(response)
  File "/home/pkkulhari/.virtualenvs/todo/lib/python3.8/site-packages/selenium/webdriver/remote/errorhandler.py", line 243, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.StaleElementReferenceException: Message: The element reference of <tr> is stale; either the element is no longer attached to the DOM, it is not in the current frame context, or the document has been refreshed
Stacktrace:
WebDriverError@chrome://remote/content/shared/webdriver/Errors.jsm:181:5
StaleElementReferenceError@chrome://remote/content/shared/webdriver/Errors.jsm:442:5
element.resolveElement@chrome://remote/content/marionette/element.js:686:11
evaluate.fromJSON@chrome://remote/content/marionette/evaluate.js:253:26
evaluate.fromJSON@chrome://remote/content/marionette/evaluate.js:261:29
receiveMessage@chrome://remote/content/marionette/actors/MarionetteCommandsChild.jsm:79:29

CodePudding user response:

You are getting a stale element reference exception, what it means is that you may have redirected to a new page after having interaction with the first element, and while coming back to the original page the elements are stale. A simple solution is to redefine the list of web elements again.

Code :

def check_row_in_table(self, rowItem):
    WebDriverWait(self.browser, 30).until(EC.visibility_of_element_located((By.CSS_SELECTOR, '#todo-items-table tr')))
    total_number_of_row = len(driver.find_elements(By.CSS_SELECTOR, "#todo-items-table tr"))
    j = 0
    for i in range(total_number_of_row):
        elems = driver.find_elements(By.CSS_SELECTOR, "#todo-items-table tr")
        self.assertIn(rowItem, elems[j].text)
        j = j   1

CodePudding user response:

I just updated the function check_row_in_table() function according to @cruisepandey's answer, and now It is working fine.

Code:

def check_row_in_table(self, rowItem):
        WebDriverWait(self.browser, 5).until(
            EC.visibility_of_all_elements_located((By.CSS_SELECTOR, '#todo-items-table tr')))

        rows = self.browser.find_elements(
            By.CSS_SELECTOR, '#todo-items-table tr')

        self.assertIn(
            rowItem,
            [row.text for row in rows]
        )
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related