Bug 183278 - Automation: stale elements not detected when removed from the DOM
Summary: Automation: stale elements not detected when removed from the DOM
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebDriver (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2018-03-02 01:04 PST by Carlos Garcia Campos
Modified: 2018-03-05 00:29 PST (History)
3 users (show)

See Also:


Attachments
Patch (2.60 KB, patch)
2018-03-02 01:06 PST, Carlos Garcia Campos
bburg: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Carlos Garcia Campos 2018-03-02 01:04:05 PST
We detect stale elements when the page is reloaded because the maps are recreated, but if an element is removed from the DOM for the same document we keep the nodes in the maps. We should clear stale elements before accessing the maps. This causes test imported/selenium/py/test/selenium/webdriver/common/webdriverwait_tests.py::testExpectedConditionStalenessOf to fail.

________________________________________________________________________ testExpectedConditionStalenessOf[WebKitGTK] _________________________________________________________________________

driver = <selenium.webdriver.webkitgtk.webdriver.WebDriver (session="2b612d84-8003-49e2-9fa6-6629e446a25f")>, pages = <conftest.Pages object at 0x7f731a9e8190>

    def testExpectedConditionStalenessOf(driver, pages):
        pages.load('dynamicallyModifiedPage.html')
        element = driver.find_element_by_id('element-to-remove')
        with pytest.raises(TimeoutException):
            WebDriverWait(driver, 0.7).until(EC.staleness_of(element))
        driver.find_element_by_id('buttonDelete').click()
        assert 'element' == element.text
>       WebDriverWait(driver, 0.7).until(EC.staleness_of(element))

driver     = <selenium.webdriver.webkitgtk.webdriver.WebDriver (session="2b612d84-8003-49e2-9fa6-6629e446a25f")>
element    = <selenium.webdriver.remote.webelement.WebElement (session="2b612d84-8003-49e2-9fa6-6629e446a25f", element="node-3C1BAE7B-915C-4AFD-995D-A1A92E529ECC")>
pages      = <conftest.Pages object at 0x7f731a9e8190>

WebDriverTests/imported/selenium/py/test/selenium/webdriver/common/webdriverwait_tests.py:254: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.support.wait.WebDriverWait (session="2b612d84-8003-49e2-9fa6-6629e446a25f")>
method = <selenium.webdriver.support.expected_conditions.staleness_of object at 0x7f731a9e8790>, message = ''

    def until(self, method, message=''):
        """Calls the method provided with the driver as an argument until the \
            return value is not False."""
        screen = None
        stacktrace = None
    
        end_time = time.time() + self._timeout
        while True:
            try:
                value = method(self._driver)
                if value:
                    return value
            except self._ignored_exceptions as exc:
                screen = getattr(exc, 'screen', None)
                stacktrace = getattr(exc, 'stacktrace', None)
            time.sleep(self._poll)
            if time.time() > end_time:
                break
>       raise TimeoutException(message, screen, stacktrace)
E       TimeoutException: Message:

end_time   = 1519977653.752561
message    = ''
method     = <selenium.webdriver.support.expected_conditions.staleness_of object at 0x7f731a9e8790>
screen     = None
self       = <selenium.webdriver.support.wait.WebDriverWait (session="2b612d84-8003-49e2-9fa6-6629e446a25f")>
stacktrace = None
value      = False

WebDriverTests/imported/selenium/py/selenium/webdriver/support/wait.py:80: TimeoutException
Comment 1 Carlos Garcia Campos 2018-03-02 01:06:59 PST
Created attachment 334885 [details]
Patch
Comment 2 BJ Burg 2018-03-02 10:44:08 PST
Comment on attachment 334885 [details]
Patch

I hope we don't have 1000's of nodes or this could get expensive. It would be nice to just check the validity of the requested node, but I guess any node could be requested via script. We'd have to find the web elements after transforming JS payload to elements.

Let's just keep this version unless we think it's actually causing a performance problem. I like simple and brute force when we can get away with it.

r=me
Comment 3 Carlos Garcia Campos 2018-03-04 02:24:26 PST
(In reply to Brian Burg from comment #2)
> Comment on attachment 334885 [details]
> Patch
> 
> I hope we don't have 1000's of nodes or this could get expensive. It would
> be nice to just check the validity of the requested node, but I guess any
> node could be requested via script. We'd have to find the web elements after
> transforming JS payload to elements.

I started the patch by only checking the requested node indeed. But then I realized that the node can be queried multiple times, so we could be checking more than once. Then I thought, let's see what chromium does, and they also clear the cache on every execute_script call, so I decided to do the same.

> Let's just keep this version unless we think it's actually causing a
> performance problem. I like simple and brute force when we can get away with
> it.

Ok.

> r=me

Thanks
Comment 4 Carlos Garcia Campos 2018-03-05 00:28:54 PST
Committed r229210: <https://trac.webkit.org/changeset/229210>
Comment 5 Radar WebKit Bug Importer 2018-03-05 00:29:20 PST
<rdar://problem/38132475>