Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

beta-13 regression - can't sendKeys to ion-inputs from protractor e2e test #15956

Closed
captaincaius opened this issue Oct 15, 2018 · 8 comments
Closed

Comments

@captaincaius
Copy link

captaincaius commented Oct 15, 2018

Bug Report

Ionic Info
Run ionic info from a terminal/cmd prompt and paste the output below.

✔ Gathering environment info - done!

Ionic:

   ionic (Ionic CLI)          : 4.1.2 (/usr/lib/node_modules/ionic)
   Ionic Framework            : @ionic/angular 4.0.0-beta.13
   @angular-devkit/core       : 0.7.5
   @angular-devkit/schematics : 0.7.5
   @angular/cli               : 6.1.5
   @ionic/ng-toolkit          : 1.0.8
   @ionic/schematics-angular  : 1.0.6

System:

   NodeJS : v8.12.0 (/usr/bin/node)
   npm    : 6.4.1
   OS     : Linux 4.15

Describe the Bug
sendKeys to element(by.css('ion-input[formControlName="username"]')) doesn't seem to work on beta.13, but it works on beta.12 ...

Steps to Reproduce

Repository here showing the problem clearly:
https://github.com/captaincaius/loadingtestcase/pull/2/files

Steps to reproduce the behavior:

  1. Create a project with an ion-input in it
  2. with protractor, target the element via element(by.css('ion-input[formControlName="username"]'))
  3. try to sendKeys to the element
  4. See error:
    "Failed: unknown error: cannot focus element"

I also tried to use deepCss on the input inside it, but that didn't work either ... i'm trying to figure out if I need to do something differently or if it's a bug to file.

Expected Behavior
protractor is able to sendKeys to the input.

Additional Context

I guess the first question here is... with all this shadow dom stuff, are we supposed to be targeting the ion-input like above, or the input inside it? I was never able to get deepCss to work even in previous betas. But targeting the ion-input like above DOES work in beta.12.

If I'm using the wrong selector above, lmk.

@ionitron-bot ionitron-bot bot added the triage label Oct 15, 2018
@captaincaius
Copy link
Author

per Mike's recommendation in slack, I will update with a dead-simple test case based on a starter template by tomorrow.

...unless, of course, you guys beat me to it and something obvi jumps out at ya ;).

@captaincaius
Copy link
Author

Updated description above with link to branch diff against ionic starter that shows the code that works on beta.12 but fails on beta.13

@sergiomilici
Copy link

I have a similar problem but when running unit tests. ion-input not updating the form. It works when I test the form manually or if I change ion-input for a regular input element.

Ionic Info

Ionic:

   ionic (Ionic CLI)             : 4.2.1 (/Users/chicho/.nvm/versions/node/v10.11.0/lib/node_modules/ionic)
   Ionic Framework               : @ionic/angular 4.0.0-beta.13
   @angular-devkit/build-angular : 0.7.5
   @angular-devkit/schematics    : 0.7.5
   @angular/cli                  : 6.1.5
   @ionic/angular-toolkit        : 1.0.0

Cordova:

   cordova (Cordova CLI) : 8.0.0
   Cordova Platforms     : none
   Cordova Plugins       : no whitelisted plugins (0 plugins total)

System:

   ios-deploy : 1.9.2
   NodeJS     : v10.11.0 (/Users/chicho/.nvm/versions/node/v10.11.0/bin/node)
   npm        : 6.4.1
   OS         : macOS High Sierra
   Xcode      : Xcode 10.0 Build version 10A255

Component

import { Component, OnInit, Input } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';

@Component({
  selector: 'edit-name',
  templateUrl: './edit-name.page.html',
  styleUrls: ['./edit-name.page.scss']
})
export class EditNamePage implements OnInit {

  modelNameForm = new FormGroup({
    modelName: new FormControl('', [Validators.required])
  });

  @Input()
  currentDisplayName = '';


  ngOnInit() {
    this.modelNameForm.setValue({
      modelName: this.currentDisplayName,
    });
  }

  onSubmit() {
  }

}

Component Template

<ion-header>
  <ion-toolbar color="primary">
    <ion-title>Test form</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content>
  <form [formGroup]="modelNameForm" (ngSubmit)="onSubmit()">
    <ion-input
            id="edit-model-name"
            autofocus="true"
            formControlName="modelName"
    >
    </ion-input>
  </form>
</ion-content>

Unit Test

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { EditNamePage } from './edit-name.page';
import { EditNamePageModule } from './edit-name.module';
import { By } from '@angular/platform-browser';

describe('EditNamePage', () => {
  let component: EditNamePage;
  let fixture: ComponentFixture<EditNamePage>;

  const setInputValue = (text: string) => {
    // get the input
    const input = fixture.debugElement.query(By.css('#edit-model-name'));
    const inputElement = input.nativeElement;

    // set input value
    inputElement.value = text;
    inputElement.dispatchEvent(new Event('input'));
  };

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [EditNamePageModule],
    })
      .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(EditNamePage);
    component = fixture.componentInstance;
  });

  it('should update the form control on input a name', () => {
    fixture.detectChanges();
    setInputValue('Beers');
    fixture.detectChanges();
    expect(component.modelNameForm.value.modelName).toBe('Beers');
  });

});

Test Result

● EditNamePage › should update the form control on input a name

expect(received).toBe(expected) // Object.is equality

Expected: "Beers"
Received: ""

  34 |     setInputValue('Beers');
  35 |     fixture.detectChanges();
> 36 |     expect(component.modelNameForm.value.modelName).toBe('Beers');
     |                                                     ^
  37 |   });
  38 |
  39 | });

It was working before with beta.11

@captaincaius
Copy link
Author

yup this problem still exists with beta 16

@sinedied
Copy link

sinedied commented Dec 14, 2018

Seems that this is due to Protractor needing the underlying input located within the shadow DOM.
The By.deepCss() locator doesn't help though as it will trigger an error saying the element is not interactable.

The only workaround I found is to add a custom locator:

by.addLocator('shadowCss', (selector, inShadowSelector, root) =>
  (root || document)
    .querySelector(selector)
    .shadowRoot
    .querySelector(inShadowSelector));

// example
element(by.shadowCss('ion-input[name=myInput]', 'input')).sendKeys('yeah!');

@mvandenbrink
Copy link

Issue still exists in 4.0.0-rc.0. The workaround works well.

@paulstelzer
Copy link
Contributor

I close this for now because it should fixed with #17043 . After rc.2 release you can check again and if it still not working, just create a comment here and I reopen.

The reason because it should work then is because ion-input not use shadow dom anymore, so the input field is now available in normal dom, no shadowroot is needed anymore

@ionitron-bot
Copy link

ionitron-bot bot commented Feb 12, 2019

Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.

@ionitron-bot ionitron-bot bot locked and limited conversation to collaborators Feb 12, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants