volnoboy volnoboy - 4 years ago 152
Java Question

Cannot input text with selenium into field with angular 2 directive

I have worked with Selenium for about 4 years. This is first time happened to me that I cannot find a proper way to send text to input field.
Our application is using angular 2 and I am sure it has something to do with it.
We have required field with angular 2 directive that checks if it's a number and later formats it(just adding commas).
When I am using regular selenium sendKeys() method, text does not appear in input field with no exception.
I have tried to use Jquery:

$("#test_borrowValue").val(770)


from selenium and google chrome console.
Text appears inside an input, but angular doesn't see it and because it is a required field it is impossible to go forward with a test.

I have tried all kind of things with selenium and js like:

action.keyDown(Keys.CONTROL).sendKeys("770").keyUp(Keys.CONTROL).perform();

$("#test_borrowValue").val(45).trigger("keydown", {which: 103});


The only thing that does work is java Robot framework or Windows api. But of course it doesn't work reliably.
Since during test nothing else could be opened, window has to be on top.
Anybody who will click anywhere on the screen in wrong moment could break the test. And in Jenkins it fails all the time.

Here is how html input looks like:

`<input id="test_borrowValue" inputNumber class="form-control require-input" formControlName="borrowValue"
[ngClass]="{requireInputError : !form.controls.borrowValue.valid && form.controls.borrowValue.touched}"/>`


And here angular 2 directive:

import { Directive, ElementRef, HostListener ,OnInit} from '@angular/core';
@Directive({
selector: '[inputNumber]'
})
export class InputNumberDtv implements OnInit {

private el:HTMLElement;

constructor(el:ElementRef) {
this.el = el.nativeElement;
}

ngOnInit():any {
this.onBlur();
}

@HostListener('keydown', ['$event']) onKeyDown(event:KeyboardEvent) {
var isNumberRegex = /^\d$/;
if (!isNumberRegex.test(event.key) && !this.permittedKeyCodes(event)) {
event.preventDefault();
}
}

@HostListener('focus') onFocus() {
$(this.el).val($(this.el).val().replace(/,/g, ""));
}

@HostListener('blur') onBlur() {
$(this.el).val($(this.el).val().replace(/\B(?=(\d{3})+(?!\d))/g, ","));
}

private permittedKeyCodes(event:KeyboardEvent) {
return event.keyCode === 46 /* Delete */
|| event.keyCode === 8 /* Backspace */
|| event.keyCode === 37 /* Arrow Left */
|| event.keyCode === 38 /* Arrow Up */
|| event.keyCode === 39 /* Arrow Right */
|| event.keyCode === 40 /* Arrow Down */
|| event.keyCode === 9 /* Tab */
|| event.keyCode === 18; /* Alt */
}
}


If I comment @HostListener block, sendKeys() method starting to work as it should. But of course we need that validation and formatting.

Looking for suggestions from selenium, js(test side) and angular 2 (development side) solutions.

Answer Source

The problem may be in this piece of code:

var isNumberRegex = /^\d$/;
  if (!isNumberRegex.test(event.key)...

check that event.key has appropriate value.

After some research it appears that because selenium web drivers don't use native events anymore, the event.key property will be empty.

So the only solution is to receive key property of the event like this:

     String.fromCharCode(event.keyCode); 

And this is the way developers have to do it. It is not related to Angular 2. Look inside this link:

https://github.com/seleniumhq/selenium/issues/386

Note: it's not only in Firefox browser.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download