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

No interaction possible with "invisible" input fields #569

Open
Gamadril opened this issue Nov 28, 2023 · 2 comments
Open

No interaction possible with "invisible" input fields #569

Gamadril opened this issue Nov 28, 2023 · 2 comments

Comments

@Gamadril
Copy link

After updating our UI from vuetify 2 to vuetify 3 no interactions is possible with input fields.
The significant change I see is the way how input field is now embedded in the vutify TextField component. In the new version the input field has the 'opactiy: 0' set which will change to 1 if the element is focused/active.
It seems that 'enter' just 'doesn't see' the corresponding input field. Also 'click' ignores it.
The current workaround is to use JS to focus the element to go on with the test, but is there an 'official' way to avoid it?

Here are the tests to show the problem.

vutify 2 (working)

|script                |browser test                                            |
|seconds before timeout|3                                                       |
|set browser size to maximum                                                    |
|open                  |https://v2.vuetifyjs.com/en/components/text-fields/#misc|
|ensure                |is visible       |State/Province/Region                 |
|enter                 |TEST             |as       |State/Province/Region       |

vuetify 3 (not working)

|script                |browser test                                         |
|seconds before timeout|3                                                    |
|set browser size to maximum                                                 |
|open                  |https://vuetifyjs.com/en/components/text-fields/#misc|
|ensure                |is visible      |State/Province/Region               |
|enter                 |TEST            |as      |State/Province/Region      |

vuetify 3 (working with workaround)

|script                |browser test                                                    |
|seconds before timeout|3                                                               |
|set browser size to maximum                                                            |
|open                  |https://vuetifyjs.com/en/components/text-fields/#misc           |
|ensure                |is visible          |State/Province/Region                      |
|execute script        |document.querySelectorAll('#custom-validation input')[3].focus()|
|enter                 |TEST                |as          |State/Province/Region         |
@fhoeben
Copy link
Owner

fhoeben commented Nov 29, 2023

Annoying these JavaScript frameworks.

I don't believe there currently is a 'standard' way to deal with this. A subclass of BrowserTest could probably hide the magic to shift focus, so the test scripts are not polluted with it. Similar tricks were needed for Angular 1 and RichFaces validations.

Having said that I expect fixing the 'click' behaviour might be possible in the generic browser test. I believe the labels are not hidden/opaque until focused so that could be an extra trick to learn browser test (I'm actually surprised it doesn't at the moment), but I haven't really looked into it.

@fhoeben
Copy link
Owner

fhoeben commented Dec 1, 2023

I managed to make click and enter work using a custom subclass.
The problems with this element turned out to be twofold:

  • when clicking BrowserTest tries to click the label, but Selenium does not want to do that because the input (although transparent) is above it and would therefore get the click (I worked around this by clicking the label using Javascript directly).
  • when entering a value the value is not intractable since it is transparent (as you found this can be fixed by focusing the element).

With a setup like this you can isolate the changes to code so the actual test/wiki pages only have to use another fixture, but their steps are the same.

|script                |vue3 test                                             |
|seconds before timeout|3                                                     |
|open                  |https://vuetifyjs.com/en/components/text-fields/#misc |
|ensure                |is visible|City                                       |
|click                 |City                                                  |
|type                  |hello                                                 |
|check                 |value of  |City                 |hello                |
|ensure                |is visible|State/Province/Region                      |
|enter                 |TEST      |as                   |State/Province/Region|
|check                 |value of  |State/Province/Region|TEST                 |

package nl.hsac.fitnesse.fixture.slim.web;

import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WebElement;

public class Vue3Test<T extends WebElement> extends BrowserTest<T>{
    @Override
    protected boolean isInteractable(WebElement element) {
        boolean interactable = super.isInteractable(element);
        if (element != null && !interactable) {
            focusElement(element);
            interactable = super.isInteractable(element);
        }
        return interactable;
    }

    @Override
    protected boolean clickElement(WebElement element) {
        return doIfInteractable(element, () -> {
            try {
                element.click();
            } catch (WebDriverException e) {
                if (clickExceptionIsAboutHiddenByOtherElement(e) && isVueHiddenElement(element)) {
                    clickWithJavascript(element);
                } else {
                    throw e;
                }
            }
        });
    }

    private Object focusElement(WebElement element) {
        return getSeleniumHelper().executeJavascript("arguments[0].focus()", element);
    }

    private boolean isVueHiddenElement(WebElement element) {
        return element.getTagName().equalsIgnoreCase("label");
    }

    private void clickWithJavascript(WebElement element) {
        getSeleniumHelper().executeJavascript("arguments[0].click()", element);
    }
}

Maybe you can use this as a starting point and see what is needed to make a fixture that is fully functional with Vue, for your suite? I would be happy to add it if you submit a PR with it.

fhoeben added a commit that referenced this issue Dec 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants