Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FluentList leads to StaleElementReferenceException #832

Open
fedotxxl opened this issue May 4, 2019 · 4 comments
Open

FluentList leads to StaleElementReferenceException #832

fedotxxl opened this issue May 4, 2019 · 4 comments
Labels

Comments

@fedotxxl
Copy link

fedotxxl commented May 4, 2019

Hello. I've got a table with rows.

        @FindBy(css = ".t-collaborator")
        private FluentList<Collaborator> collaborators;

My test does the following:

  1. Check rows content
  2. Add one more row
  3. Check rows content

On step 3 I've got org.openqa.selenium.StaleElementReferenceException exception. I tried to use reset() with no luck. How can I reset fluent list state?

@slawekradzyminski
Copy link
Member

Hi fedotxxl. Do you use the latest version? If yes can you please share piece of code which triggers it?

@fedotxxl
Copy link
Author

fedotxxl commented May 4, 2019

I use version 3.8.1 because of Java 8.

Here is sample code:

public class Main {
    public static class RepoCollaborationsTabComponent extends FluentWebElement {

        @FindBy(css = "table.t-collaborators")
        private RepoCollaborationsTabComponent.Table table;

        public void assertCollaborators(List<RepoCollaborationsTabComponent.Collaborator> collaborators) {
            assertThat(table.getCollaboratorsData()).isEqualTo(collaborators);
        }
    }

    public static class Table extends FluentWebElement {

        @FindBy(css = ".t-collaborator")
        private FluentList<RepoCollaborationsTabComponent.Table.Collaborator> collaborators;

        public List<RepoCollaborationsTabComponent.Collaborator> getCollaboratorsData() {
            return collaborators.stream()
                    .map(RepoCollaborationsTabComponent.Table.Collaborator::getData)
                    .collect(Collectors.toList());
        }

        public static class Collaborator extends FluentWebElement {

            @FindBy(css = ".t-collaborator--email")
            private FluentWebElement email;

            @FindBy(css = ".t-collaborator--invite-not-accepted")
            private FluentWebElement inviteNotAcceptedIcon;
        }
    }

}

When I call assertCollaborators the first time it works as expected. When I call it after table change (adding new collaborator) table.collaborators contains the previous list of collaborators and org.openqa.selenium.StaleElementReferenceException is thrown.

@slawekradzyminski
Copy link
Member

slawekradzyminski commented May 8, 2019

Thanks @fedotxxl for report. Improving stream() may not be easy, but I'll try in free time.

Probably the same root cause as #787

@famoser
Copy link

famoser commented May 11, 2022

Failing test case which exposes the root cause (to be placed within WaitComponentsListTest):

@Test
void shouldReturnActualValueFromTheInternalChangedList() {
	goTo(ELEMENT_REPLACE_URL);
	await().until(rowsListPage.getComponentsList()).size(2);
	assertThat(rowsListPage.getComponentsList().size()).isEqualTo(2);
	await().until(rowsListPage.getComponentsList()).size(4);
	assertThat(rowsListPage.getComponentsList().size()).isEqualTo(4);
}

The issue seems to be that FluentList maintains internal list state (within DelegatingList) which is resolved once, but then not updated. Using any method which uses the internal FluentList state (instead of going over LocatorProxies) may return an outdated result.

This leads to the following failing use cases:

  • Access list.textContents(), navigate, access list.textContents() again -> StaleElementReferenceException
  • Using list.size(), navigate, list.size() -> the second call may returns a wrong result

For a list of affected use cases see the methods implemented in the interface FluentList using stream() (as stream will always access the internal FluentList state, instead of using the LocatorProxies).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants