shentao / vue-multiselect

Universal select/multiselect/tagging component for Vue.js
https://vue-multiselect.js.org/
MIT License
6.72k stars 991 forks source link

Can't interact via selenium #926

Open ianwremmel opened 5 years ago

ianwremmel commented 5 years ago

I'm attempting to write a selenium test that involves submitting a form that includes a vue-multiselect and I can't find any thing for selenium to click on that opens the options list.

Similarly, I can't find any JavaScript to run from dev tools that would open the options at https://vue-multiselect.js.org/. For example, I would expect something like document.querySelector('.multiselect').click() to open the options list.

Reproduction Link

https://vue-multiselect.js.org/

Steps to reproduce

  1. Visit https://vue-multiselect.js.org/
  2. Open dev tools
  3. Highlight various DOM nodes related to the main vue-multiselect on the page and run $0.click()
  4. Note that the options never appear

Expected behaviour

There should be some DOM node that receives a JavaScript or Selenium click event that causes the options list to appear

Actual behaviour

The options list does not appear.

rnicholus commented 5 years ago

Also seeing this issue. Something broke this behavior in one of the latest versions, as I was definitely able to open the dropdown via click in a Selenium test w/ v2.0.8.

ianwremmel commented 5 years ago

Good to know that it did work as one would expect. I did get my tests working with selenium's click, but not dev tools. It seems to have something to do with whether the document has focus; IIRC, i could get the dev tools top open the dropdown with setTimeout(() => $0.click(), 3000) if i clicked into the document first.

rnicholus commented 5 years ago

i ended up reverting to v2.0.8 as I ran into a number of other regressions and breaking changes w/ the library

shentao commented 5 years ago

Hey! Would you be able to identify what exactly has caused this regression? I also wonder if this also happens on the v3 branch. Though in 3.0 the multiselect requires more than just focus to properly activate.

rnicholus commented 5 years ago

I looked for a short time, and wasn't able to immediately determine what was causing this. I ran out of time and had to revert. Sorry I couldn't be more helpful 😞

tiec7 commented 3 years ago

I have the same issue, too, using version 2.1.6. Unable to open the multiselect or click to any of their elements; the error given is "element not interactable". If I try to wait for simply element to be visible, it goes in timeout.

velis74 commented 3 years ago

Same issue. Made a stupid workaround where I defined some accessor functions in the window namespace in mounted and destroyed. No clicking: I just use the reactive stuff and set variables. I don't need to test the select component itself.

It does present a challenge still since it behaves completely differently than an actual select.

shentao commented 3 years ago

Is selenium somehow behind in how you can interact with the DOM compared to say Cypress? I haven’t had any issues with interacting with the component using the latter. What really helps is creating a Page Object that simplifies the interactions and using that instead.

ianwremmel commented 3 years ago

Cypress is entirely JavaScript and doesn't use any automation built into the browser while selenium only uses automation built into the browser. I don't know that "behind" is the right word, they're just fundamentally different.

I haven't used vue-multiselect for a few years (partly because of this, but mostly because various organization changes have me writing react these days), but I'm not sure how a PageObject would help here. The problem, at least when I used the library, was not around code organization, but was instead around an inability to find any event target that would cause the options to appear.

Are you saying Cypress can interact with a vue-multiselect input?

tiec7 commented 3 years ago

I gave up months ago switching to cypress. more reliable, more handy, faster.

shentao commented 3 years ago

Sadly I’m not an expert on Selenium (it’s been years since I last touched it and back then I was hardly proficient with e2e tests). Generally, with Cypress it works pretty decently, especially once you abstract the interactions into a PageObject. In one of my projects we use it like this:

new MultipleSelect({ label: 'Select User' })
          .toggle()
          .shouldHaveOptions([
            'John Doe',
            'Jane Doe',
          ])
          .select('John Doe')

The page object is implemented like this:

class MultipleSelect extends FormElement {
  getSearchInput () {
    return this.getElement().find('.multiselect__input')
  }

  getValue () {
    return this.getElement().find('.multiselect__single')
  }

  getTrigger () {
    return this.getElement().find('.multiselect__select')
  }

  getOptions () {
    return this.getElement().find('.multiselect__content')
  }

  toggle () {
    this.getTrigger().click({ force: true })
    return this
  }

  select (label) {
    this.getOptions()
      .contains(label, { timeout: 15000 })
      .click({ force: true })
    return this
  }

  shouldHaveOptions (options) {
    this.getOptions().within(() => {
      cy.get('.multiselect__element').should('have.length', options.length)

      options.forEach(option => {
        cy.findByText(option).should('exist')
      })
    })
    return this
  }

  // more helper functions here

And it really works pretty smoothly. Though I agree that without a page object, memorizing all the CSS classes to access the contents is frustrating, to say the least.

Not sure if this will be helpful in any way for Selenium users though...