module-webdriver icon indicating copy to clipboard operation
module-webdriver copied to clipboard

Fill field in numeric value with slider appends the value into the current one.

Open annapetrai opened this issue 7 years ago • 10 comments

What are you trying to achieve?

I am trying to fill the field with a simple value.

What do you get instead?

The value is appended at the end of the current value.

annapetrai avatar Aug 08 '18 09:08 annapetrai

Please provide your test code, configuration and example of HTML.

Naktibalda avatar Aug 08 '18 09:08 Naktibalda

<input type="number" id="sliderInput"  min="1" max="666.00" step="1">
I->fillfield('#sliderInput','1'); 

annapetrai avatar Aug 08 '18 09:08 annapetrai

I am using selenium docker the latest.Codeception version the latest.

annapetrai avatar Aug 08 '18 09:08 annapetrai

Do you want the yml configuration?

annapetrai avatar Aug 08 '18 09:08 annapetrai

fillField clears the field then sends keypresses to the field. https://github.com/Codeception/Codeception/blob/2.4.5/src/Codeception/Module/WebDriver.php#L1643-L1644

Suggestions:

  1. Check if $I->clearField('#sliderInput'); has any effect on a slider.
  2. Test with a different browser to see if it is a browser specific issue.
  3. Look for slider related issues in repository of your browser's driver (chromedriver, geckodriver, etc). If you are too lazy for this, tell me what browser you are using).

Naktibalda avatar Aug 08 '18 12:08 Naktibalda

I run xdebug on web driver functions and I see that it does not clear the field.The I ->clearField function does not work.


    /**
     * If this element is a TEXTAREA or text INPUT element, this will clear the value.
     *
     * @return WebDriverElement The current instance.
     */
    public function clear();

I see the following I have declared it as a numeric field maybe that could be the problem.But I have the same field with the same characteristics and it works perfectly fine. I also used this way to fill the value and it seems to work but the way is not appropriate.

   $I->executeJS('$("' . $sliderInput . '").val(arguments[0])', [$value]);
   $I->executeJS(''$("' . $sliderInput . '").blur()");

I am using chrome latest version.

annapetrai avatar Aug 08 '18 12:08 annapetrai

Also I have something extra in that field it has a format of of two desimals.

annapetrai avatar Aug 08 '18 12:08 annapetrai

I am doing two and three currently I will tell you the results after my tests.

annapetrai avatar Aug 08 '18 13:08 annapetrai

We stumbled over the same problem (using Chrome 71 and Codeception 2.5.1):

  • For this HTML <input type="number" id="quantity" name="quantity" min="1" value="3">
  • ... this did not work: $I->fillfield('#quantity','2')
  • ... as it lead to a value of '12' instead of '2'

After looking at the Codeception source code it is obvious why $I->clearField('#quantity') does not work (or rather does not help): fillField(...) is actually doing that already as well at the very beginning.

And the reason or root cause seems to be the min="1" (that is available for certain input fields types like number): due to loss of focus (or so?) after the clearField(...) call the minimum value is auto-inserted or defaulted immediately.

This leads to our workaround based on preventing the loss of focus by (1) selecting everything (in the field) and (2) immediately overwriting the selection (= old value) with the (new) desired value: $I->pressKey('#quantity', [\WebDriverKeys::CONTROL, 'a'], (string)$quantity)

Frankly I am not sure if it would be desirable or common in Codeception source code to implement this rather special auto-magic handling?

reinholdfuereder avatar Feb 07 '19 07:02 reinholdfuereder

Oops, sorry, I must correct myself:

  • the above (just the input field) is not sufficient to reproduce the problem
  • in our case there was an additional JavaScript on-change event handler that defaulted to a '1' in case the current input was no integer, something like this:
var field =document.querySelector('input[name="quantity"]');
field.addEventListener('change', function() {
  if (!parseInt(field.value)) {
    field.value = (1).toString();
  }
})

However, in our mind it is still (very much) debatable, whether or not the Codeception implementation for fillField(...) (to first clearField and only in the second step sending the keys i.e. the new value; at least for such input fields?) is the correct/best one, as it actually may behave unexpectedly by triggering more than a single on-change event, and thus leading to unexpected (test) behaviour (like in our case).

reinholdfuereder avatar Feb 15 '19 09:02 reinholdfuereder