vue-frag
vue-frag copied to clipboard
Elements inside vue-frag are invisible in Selenium
What's wrong
- Make this Vue component:
<!-- src/MyFrag.vue -->
<template>
<div v-frag>
<div id="1">I'm invisible to selenium!</div>
<div id="2">I'm invisible to selenium!</div>
</div>
</template>
<script>
export default {}
</script>
- Display it on localhost:3000
<!-- App.vue -->
<template>
<MyFrag/>
</template>
<script>
import MyFrag from '@/MyFrag.vue'
export default {
components: {MyFrag}
}
</script>
- Try to find the element using Selenium - it will be found, but Selenium will interpret it as if it's not visible.
It's worth mentioning that:
- The
div v-frag
children are visible in the HTML in the inspector - The children are also visible to the human eye - I'd be able to see the "I"m invisible to selenium!" texts.
//selenium code in C#
this.driver.FindElement(By.CssSelector("[id='1']")).Displayed //returns "False"
HTML in question:
Expected behavior
v-frag children that are clearly visible (no v-if etc.) should show up as displayed: true
when trying to select them with Selenium.
Current behavior
v-frag children that are clearly visible (no v-if etc.) show up as displayed: false
Additional notes
-
A related issue I've found in the Selenium repo is this - it talks about vue-fragment, not vue-frag but the issue is similar is here: https://github.com/SeleniumHQ/selenium/issues/9668 . Not sure if it's very useful to this issue, since judging by the OP, vue-fragment's and vue-frag's implementations are very different.
-
I've read through this part of the readme: https://github.com/privatenumber/vue-frag#how-does-this-work and immediately this part caught my attention:
The Frag directive simply replaces the root element of a component in the DOM with it's children upon DOM insertion, and monkey-patches native properties like parentNode on the children to make Vue think they're still using the component root element.
I'm suspecting there's some edge case in the monkey-patching that's making Selenium think the v-frag children are hidden. Since Selenium probably traverses the very same native properties that are monkeypatched.
I understand this issue really needs a minimal repro. I'm at work right now but I'll try to set something up quickly. I just don't think it'll be possible to avoid installing some deps like .NET Core or Java to repro this :P
Seems like a bug in Selenium rather than vue-frag.
There isn't any code in vue-frag that sets display: none
or in the monkey-patching to make it seem like an element is hidden.
@3nuc Can you please try getText()
on this.driver.FindElement(By.CssSelector("[id='1']"))
. The output should be I'm invisible to selenium!
Here's the minimal repro, turns out there's a JS binding for Selenium webdriver so no .NET needed (same issue happens with .NET and JS): https://github.com/3nuc/vue-frag-issue-35 - instructions are in the readme
@spbrantan In my case the getText() returns an empty string or newline
Output from Selenium (node selenium.js)
t430 :: ~/dev/vue-frag-issue-35 ‹master› % node selenium.js
for element INSIDE v-frag:
isDisplayed: false
getText:
for element OUTSIDE v-frag:
isDisplayed: true
getText: On the other hand - I'm visible to selenium because I'm outside v-frag
for the following output html from Vue from localhost:8080
<div id="app">
<div id="1">I'm invisible to selenium!</div>
<div id="2">I'm invisible to selenium!</div>
<div id="ok"> On the other hand - I'm visible to selenium because I'm outside v-frag </div>
</div>
Can you see if the new release makes any improvements here?
The getText()
returning an empty string is expected behavior because the fragment's innerText
or textContent
aren't patched.
Here are the APIs that are actually patched: https://github.com/privatenumber/vue-frag#how-does-this-work
@privatenumber I'm getting the same result as in my previous commit on 1.3.1 (both getText empty and wrongly isDisplayed: false).
So you're saying vue-frag would need to have patching for innerText and visibility even though it's not strictly necessary for the fragment logic? ie. purely for the sake of Selenium
Bummer 😔 There's more coverage in API patching (eg. childNodes) so I was hoping Selenium would get better data.
I'm not sure what's causing Selenium to think the element is hidden. But regarding the innerText
, yes, extra patching will need to be applied that won't serve the general use-case.
Seems there's some new info in https://github.com/SeleniumHQ/selenium/issues/9668#issuecomment-1003167647 . Thought I'd ping about it here for notification reasons
I also have this issue when using vue-frag. Though for me selenium can't initiate dom events like click
add $(element).css({"overflow": "visible", "position": "static"}); in function inserted will resolve this issue
I don't plan on supporting Selenium so I'm closing this, but feel free to discuss workarounds.