I'm new to Python and Selenium testing so please forgive me if this isn't written right. I've been asked to look at the test that does a few actions on a form. The form has 2 text fields, a drop down, and a button. The test is rather simple:
self.wd.wait_for_css('.js-status-code-input').send_keys('100') self.wd.find_css('.js-description-input').send_keys('Approved') status_select = Select(self.wd.find_css('.js-status-input')) status_select.select_by_value('APPRV') self.wd.wait_for_css('#js-add-mapping-btn').click()
When run, we get an error at the very end: Element is not currently visible and so may not be interacted with
So - I did some debugging and noticed something odd. When select_by_value is run, the entire form goes away. And in fact, if I look at the position of js-add-mapping-btn, it has a y value set above the top of the browser. Before select_by_value, it is normal.
To make things even more interesting, if I change APPRV to whatever is the default option, it doesn't make the form disappear and the test passes.
If I use select_by_index, it is the exact same behavior. Using 1 as a value causes the bug, using 0 makes it pass.
So it seems like select_by_value, when it changes stuff, is breaking the site. I've removed any client-side JS code validation on the form. I've also tested manually, in the same browser, entering the same values, and I can't reproduce what I see when the webdriver drives Firefox along.
Edit on Sep 2 I was gone for a few days on vacation and my coworker made some discoveries. What follows is credit Alan Greenblatt:
Aha! I've made some progress on this one. I stepped into status_select.select_by_value('APPRV'), which is defined as:
def select_by_value(self, value): """Select all options that have a value matching the argument. That is, when given "foo" this would select an option like: <option value="foo">Bar</option> :Args: - value - The value to match against """ css = "option[value =%s]" % self._escapeString(value) opts = self._el.find_elements(By.CSS_SELECTOR, css) matched = False for opt in opts: self._setSelected(opt) if not self.is_multiple: return matched = True if not matched: raise NoSuchElementException("Cannot locate option with value: %s" % value)
Then I stopped on the 'self._setSelected(opt)' line. All is still good in the UI at this point. If you print out 'opt', the UI goes kerflooey. So, I tried printing out each attribute of opt individually. It turns out that the problem occurs only when you try to resolve opt.location_once_scrolled_into_view.
In the firefox driver js source, it looks like this will actually scroll the element into view. I'm betting this is where the problem lies.
and then later
I stopped at the same line, but then went into Firefox's Web Developer debugger and executed the following line:
and was able to reproduce the problem.
and then later again...
looks good, but
$.find('.js-status-input').options.scrollIntoView(true) or $.find('.js-status-input').options.scrollIntoView()