marracuene
marracuene

Reputation: 171

Cypress with an Ionic app: cannot access ion-select-option because it is "not visible"

I have a have an ionic/angular app which contains a particular form-control as follows:

<ion-select #typeLst interface="alert" name="typeCode" formControlName="typeCode" okText="OK" cancelText="Dismiss" placeholder="Choose a firm type">
      <ion-select-option value="EPFIRMI001">Informal</ion-select-option>
      <ion-select-option value="EPFIRMF001">Formal/Ltd.</ion-select-option>
 </ion-select>

In my cypress test, I can navigate to the page and do other things on it but when I try to select a specific item on the "select" cypress is 'aware' of it but cannot access it.

Cypress code:

cy.get('ion-select[name="typeCode"]').click()

cy.get('ion-select-option[value="EPFIRMF001"]').click()

Cypress error:

Timed out retrying: cy.click() failed because this element is not visible:

<ion-select-option _ngcontent-dqd-c137="" value="EPFIRMF001" ng-reflect-value="EPFIRMF001" role="option" id="ion-selopt-1" class="md hydrated">Formal/...</ion-select-option>

This element <ion-select-option#ion-selopt-1.md.hydrated> is not visible because it has CSS property: display: none

Fix this problem, or use `{force: true}` to disable error checking.

N.B:

Versions:

EDIT 09/08/2020 In response (too long for a comment) to @SanjaPaskova's second suggestion: Using select as follows: cy.get('ion-select[name="typeCode"]').select('Formal') ...produces following error message:

cy.select() can only be called on a <select>. Your subject is a: <ion-select _ngcontent-jql-c137="" interface="alert " name="typeCode" formcontrolname="typeCode" oktext="OK" canceltext="Dismiss" placeholder="Choose a firm type" ng-reflect-interface="alert " ng-reflect-name="typeCode" ng-reflect-ok-text="OK" ng-reflect-cancel-text="Dismiss" ng-reflect-placeholder="Choose a firm type" class="ng-untouched ng-pristine ng-valid ion-untouched ion-pristine ion-valid md in-item hydrated" role="combobox" aria-haspopup="dialog" aria-expanded="true" aria-labelledby="ion-sel-0-lbl">...</ion-select>

Ionic/Angular source is above in my original post. This produces the below generated DHTML:

<ion-card-content _ngcontent-nld-c140="" class="md card-content-md hydrated"><form _ngcontent-nld-c140="" novalidate="" class="outer ng-untouched ng-pristine ng-valid" ng-reflect-form="[object Object]"><ion-item _ngcontent-nld-c140="" class="ion-untouched ion-pristine ion-valid item md ion-activatable ion-focusable item-label hydrated item-interactive item-select item-has-placeholder item-has-value"><ion-label _ngcontent-nld-c140="" class="sc-ion-label-md-h sc-ion-label-md-s md hydrated" id="ion-sel-0-lbl">Type: </ion-label><ion-select _ngcontent-nld-c140="" interface="alert
    " name="typeCode" formcontrolname="typeCode" oktext="OK" canceltext="Dismiss" placeholder="Choose a firm type" ng-reflect-interface="alert
    " ng-reflect-name="typeCode" ng-reflect-ok-text="OK" ng-reflect-cancel-text="Dismiss" ng-reflect-placeholder="Choose a firm type" class="ng-untouched ng-pristine ng-valid ion-untouched ion-pristine ion-valid md in-item hydrated" role="combobox" aria-haspopup="dialog" aria-expanded="false" aria-labelledby="ion-sel-0-lbl"><ion-select-option _ngcontent-nld-c140="" value="EPFIRMI001" ng-reflect-value="EPFIRMI001" role="option" id="ion-selopt-0" class="md hydrated">Informal</ion-select-option><ion-select-option _ngcontent-nld-c140="" value="EPFIRMF001" ng-reflect-value="EPFIRMF001" role="option" id="ion-selopt-1" class="md hydrated">Formal/Ltd.</ion-select-option><input type="hidden" class="aux-input" name="typeCode" value="EPFIRMI001"></ion-select></ion-item><ion-item _ngcontent-nld-c140="" class="ion-untouched ion-pristine ion-valid item md ion-focusable item-label hydrated item-interactive item-input"><ion-label _ngcontent-nld-c140="" class="sc-ion-label-md-h sc-ion-label-md-s md hydrated" id="ion-input-1-lbl">Company name:</ion-label><ion-input _ngcontent-nld-c140="" formcontrolname="name" ng-reflect-name="name" class="ng-untouched ng-pristine ng-valid ion-untouched ion-pristine ion-valid sc-ion-input-md-h sc-ion-input-md-s md hydrated"><input class="native-input sc-ion-input-md" aria-labelledby="ion-input-1-lbl" autocapitalize="off" autocomplete="off" autocorrect="off" name="ion-input-1" placeholder="" type="text"></ion-input></ion-item><ion-item _ngcontent-nld-c140="" class="ion-untouched ion-pristine ion-valid item md ion-focusable item-label hydrated item-interactive item-input"><ion-label _ngcontent-nld-c140="" class="sc-ion-label-md-h sc-ion-label-md-s md hydrated" id="ion-input-2-lbl">Tax ID (NUIT):</ion-label><ion-input _ngcontent-nld-c140="" formcontrolname="taxId" ng-reflect-name="taxId" class="ng-untouched ng-pristine ng-valid ion-untouched ion-pristine ion-valid sc-ion-input-md-h sc-ion-input-md-s md hydrated"><input class="native-input sc-ion-input-md" aria-labelledby="ion-input-2-lbl" autocapitalize="off" autocomplete="off" autocorrect="off" name="ion-input-2" placeholder="" type="text"></ion-input></ion-item><ion-fab-button _ngcontent-nld-c140="" class="md ion-activatable ion-focusable hydrated"><ion-icon _ngcontent-nld-c140="" name="checkmark-outline" ng-reflect-name="checkmark-outline" role="img" class="md hydrated" aria-label="checkmark outline"></ion-icon></ion-fab-button></form></ion-card-content>

EDIT 02/05/2021 The solution below from @VégerLóránd works, however note that when I have finally had a use case which allowed me to test it, my stack had upgraded to the following:

Versions:

I tested the below solution for interface="alert". I also modified it as below for interface="action-sheet"and this worked too.

        cy.get('[cy-data=type] > ion-select').should((e) =>
        {
            const [dom] = e.get();
            dom.shadowRoot.querySelector('button').click();
        });
        cy.contains('.action-sheet-button', 'Your location name').click();
        //no need to click 'OK' when interface="action-sheet"

Upvotes: 6

Views: 2364

Answers (3)

marracuene
marracuene

Reputation: 171

Thanks @d-hodges for the poke. Here is how we eventually got it to work, at least for <ion-select interface="action-sheet"> - this is based on the answer from @VégerLóránd

Form Control code

<ion-select formControlName="type" interface="action-sheet" placeholder="{{'Product Type' | translate}}">
                        <ion-select-option *ngFor="let t of productTypes" value="{{t.code}}">{{t.description}}</ion-select-option>
</ion-select>

Cy E2E code to select 'Beverage' (one of the possible user-visible values on the description).

cy.get('[cy-data=type] > ion-select').should((e) =>
{
     const [dom] = e.get();
     dom.shadowRoot.querySelector('button').click();
});
cy.contains('.action-sheet-button', 'Beverage').click();

Upvotes: 2

This is how I resolved it, maybe it can help to you as well. I wrapped ion-select with an ion-item element and added cy-data='location' attribute to it.

<ion-item class="ion-no-padding ion-margin-horizontal" cy-data="location">
  <ion-label color="primary">{{ 'location' | translate }}</ion-label>
  <ion-select [(ngModel)]="location" [disabled]="locationDisabled" >
    <ion-select-option *ngFor="let location of locations" value="{{location._id}}">{{location.name}}</ion-select-option>
  </ion-select>
</ion-item>

In the test file this is how you can access to the select:

cy.get('[cy-data=location] > ion-select').should((e) => {
  const [dom] = e.get();
  dom.shadowRoot.querySelector('button').click();
});
cy.contains('.alert-radio-label', 'Your location name').click();
cy.contains('OK').click();

In my case after i clicked the button in the shadowRoot (so the select drop down list itself) the select list appears with location names and with a button what contains OK. So if you have different scenario you need to change these details.

Upvotes: 4

Sanja Paskova
Sanja Paskova

Reputation: 1110

You can invoke showing of element if is hidden, like this:

cy.get('ion-select-option[value="EPFIRMF001"]').invoke('show');

and then you can click it:

cy.get('ion-select-option[value="EPFIRMF001"]').click()

Upvotes: -1

Related Questions